Variabiliteit van steekproef tot steekproef
Om te begrijpen dat een steekproef random is zouden we hetzelfde experiment veel keer moeten kunnen herhalen (repeated sampling).
Dan zouden we inzicht kunnen krijgen hoe de gegevens veranderen van steekproef tot steekproef.
Om dit te illustreren zullen we gebruik maken van een hele grote studie.
Uit die studie zullen we dan herhaaldelijk kleine steekproeven trekken om te begrijpen hoe de gegevens en statistieken veranderen van steekproef tot steekproef. Of om met andere woorden na te gaan wat de variabiliteit is tussen steekproeven.
National Health NHanes study
- Sinds 1960 worden elk jaar mensen van alle leeftijden geïnterviewd bij hen thuis.
- Er maakt ook een gezondheidsonderzoek deel uit van de study die in een mobiel onderzoekscentrum wordt afgenomen.
- We zullen deze grote studie gebruiken om at random personen te selecteren van de Amerikaanse populatie.
- Dat zal inzicht geven in hoe de gegevens en resultaten van een analyse zullen variëren van steekproef tot steekproef.
- De data van deze studie is terug te vinden in het R pakket
NHANES
library(NHANES)
head(NHANES)
# A tibble: 6 x 77
ID SurveyYr Gender Age AgeDecade AgeMonths Race1 Race3 Education
<int> <fct> <fct> <int> <fct> <int> <fct> <fct> <fct>
1 51624 2009_10 male 34 " 30-39" 409 White <NA> High Sch…
2 51624 2009_10 male 34 " 30-39" 409 White <NA> High Sch…
3 51624 2009_10 male 34 " 30-39" 409 White <NA> High Sch…
4 51625 2009_10 male 4 " 0-9" 49 Other <NA> <NA>
5 51630 2009_10 female 49 " 40-49" 596 White <NA> Some Col…
6 51638 2009_10 male 9 " 0-9" 115 White <NA> <NA>
# … with 68 more variables: MaritalStatus <fct>, HHIncome <fct>,
# HHIncomeMid <int>, Poverty <dbl>, HomeRooms <int>, HomeOwn <fct>,
# Work <fct>, Weight <dbl>, Length <dbl>, HeadCirc <dbl>, Height <dbl>,
# BMI <dbl>, BMICatUnder20yrs <fct>, BMI_WHO <fct>, Pulse <int>,
# BPSysAve <int>, BPDiaAve <int>, BPSys1 <int>, BPDia1 <int>,
# BPSys2 <int>, BPDia2 <int>, BPSys3 <int>, BPDia3 <int>,
# Testosterone <dbl>, DirectChol <dbl>, TotChol <dbl>, UrineVol1 <int>,
# UrineFlow1 <dbl>, UrineVol2 <int>, UrineFlow2 <dbl>, Diabetes <fct>,
# DiabetesAge <int>, HealthGen <fct>, DaysPhysHlthBad <int>,
# DaysMentHlthBad <int>, LittleInterest <fct>, Depressed <fct>,
# nPregnancies <int>, nBabies <int>, Age1stBaby <int>,
# SleepHrsNight <int>, SleepTrouble <fct>, PhysActive <fct>,
# PhysActiveDays <int>, TVHrsDay <fct>, CompHrsDay <fct>,
# TVHrsDayChild <int>, CompHrsDayChild <int>, Alcohol12PlusYr <fct>,
# AlcoholDay <int>, AlcoholYear <int>, SmokeNow <fct>, Smoke100 <fct>,
# Smoke100n <fct>, SmokeAge <int>, Marijuana <fct>, AgeFirstMarij <int>,
# RegularMarij <fct>, AgeRegMarij <int>, HardDrugs <fct>, SexEver <fct>,
# SexAge <int>, SexNumPartnLife <int>, SexNumPartYear <int>,
# SameSex <fct>, SexOrientation <fct>, PregnantNow <fct>, gender <dbl>
Observations: 10,000
Variables: 77
$ ID <int> 51624, 51624, 51624, 51625, 51630, 51638, 51646…
$ SurveyYr <fct> 2009_10, 2009_10, 2009_10, 2009_10, 2009_10, 20…
$ Gender <fct> male, male, male, male, female, male, male, fem…
$ Age <int> 34, 34, 34, 4, 49, 9, 8, 45, 45, 45, 66, 58, 54…
$ AgeDecade <fct> 30-39, 30-39, 30-39, 0-9, 40-49, 0-9, 0-…
$ AgeMonths <int> 409, 409, 409, 49, 596, 115, 101, 541, 541, 541…
$ Race1 <fct> White, White, White, Other, White, White, White…
$ Race3 <fct> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
$ Education <fct> High School, High School, High School, NA, Some…
$ MaritalStatus <fct> Married, Married, Married, NA, LivePartner, NA,…
$ HHIncome <fct> 25000-34999, 25000-34999, 25000-34999, 20000-24…
$ HHIncomeMid <int> 30000, 30000, 30000, 22500, 40000, 87500, 60000…
$ Poverty <dbl> 1.36, 1.36, 1.36, 1.07, 1.91, 1.84, 2.33, 5.00,…
$ HomeRooms <int> 6, 6, 6, 9, 5, 6, 7, 6, 6, 6, 5, 10, 6, 10, 10,…
$ HomeOwn <fct> Own, Own, Own, Own, Rent, Rent, Own, Own, Own, …
$ Work <fct> NotWorking, NotWorking, NotWorking, NA, NotWork…
$ Weight <dbl> 87.4, 87.4, 87.4, 17.0, 86.7, 29.8, 35.2, 75.7,…
$ Length <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
$ HeadCirc <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
$ Height <dbl> 164.7, 164.7, 164.7, 105.4, 168.4, 133.1, 130.6…
$ BMI <dbl> 32.22, 32.22, 32.22, 15.30, 30.57, 16.82, 20.64…
$ BMICatUnder20yrs <fct> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
$ BMI_WHO <fct> 30.0_plus, 30.0_plus, 30.0_plus, 12.0_18.5, 30.…
$ Pulse <int> 70, 70, 70, NA, 86, 82, 72, 62, 62, 62, 60, 62,…
$ BPSysAve <int> 113, 113, 113, NA, 112, 86, 107, 118, 118, 118,…
$ BPDiaAve <int> 85, 85, 85, NA, 75, 47, 37, 64, 64, 64, 63, 74,…
$ BPSys1 <int> 114, 114, 114, NA, 118, 84, 114, 106, 106, 106,…
$ BPDia1 <int> 88, 88, 88, NA, 82, 50, 46, 62, 62, 62, 64, 76,…
$ BPSys2 <int> 114, 114, 114, NA, 108, 84, 108, 118, 118, 118,…
$ BPDia2 <int> 88, 88, 88, NA, 74, 50, 36, 68, 68, 68, 62, 72,…
$ BPSys3 <int> 112, 112, 112, NA, 116, 88, 106, 118, 118, 118,…
$ BPDia3 <int> 82, 82, 82, NA, 76, 44, 38, 60, 60, 60, 64, 76,…
$ Testosterone <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
$ DirectChol <dbl> 1.29, 1.29, 1.29, NA, 1.16, 1.34, 1.55, 2.12, 2…
$ TotChol <dbl> 3.49, 3.49, 3.49, NA, 6.70, 4.86, 4.09, 5.82, 5…
$ UrineVol1 <int> 352, 352, 352, NA, 77, 123, 238, 106, 106, 106,…
$ UrineFlow1 <dbl> NA, NA, NA, NA, 0.094, 1.538, 1.322, 1.116, 1.1…
$ UrineVol2 <int> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
$ UrineFlow2 <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
$ Diabetes <fct> No, No, No, No, No, No, No, No, No, No, No, No,…
$ DiabetesAge <int> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
$ HealthGen <fct> Good, Good, Good, NA, Good, NA, NA, Vgood, Vgoo…
$ DaysPhysHlthBad <int> 0, 0, 0, NA, 0, NA, NA, 0, 0, 0, 10, 0, 4, NA, …
$ DaysMentHlthBad <int> 15, 15, 15, NA, 10, NA, NA, 3, 3, 3, 0, 0, 0, N…
$ LittleInterest <fct> Most, Most, Most, NA, Several, NA, NA, None, No…
$ Depressed <fct> Several, Several, Several, NA, Several, NA, NA,…
$ nPregnancies <int> NA, NA, NA, NA, 2, NA, NA, 1, 1, 1, NA, NA, NA,…
$ nBabies <int> NA, NA, NA, NA, 2, NA, NA, NA, NA, NA, NA, NA, …
$ Age1stBaby <int> NA, NA, NA, NA, 27, NA, NA, NA, NA, NA, NA, NA,…
$ SleepHrsNight <int> 4, 4, 4, NA, 8, NA, NA, 8, 8, 8, 7, 5, 4, NA, 5…
$ SleepTrouble <fct> Yes, Yes, Yes, NA, Yes, NA, NA, No, No, No, No,…
$ PhysActive <fct> No, No, No, NA, No, NA, NA, Yes, Yes, Yes, Yes,…
$ PhysActiveDays <int> NA, NA, NA, NA, NA, NA, NA, 5, 5, 5, 7, 5, 1, N…
$ TVHrsDay <fct> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
$ CompHrsDay <fct> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
$ TVHrsDayChild <int> NA, NA, NA, 4, NA, 5, 1, NA, NA, NA, NA, NA, NA…
$ CompHrsDayChild <int> NA, NA, NA, 1, NA, 0, 6, NA, NA, NA, NA, NA, NA…
$ Alcohol12PlusYr <fct> Yes, Yes, Yes, NA, Yes, NA, NA, Yes, Yes, Yes, …
$ AlcoholDay <int> NA, NA, NA, NA, 2, NA, NA, 3, 3, 3, 1, 2, 6, NA…
$ AlcoholYear <int> 0, 0, 0, NA, 20, NA, NA, 52, 52, 52, 100, 104, …
$ SmokeNow <fct> No, No, No, NA, Yes, NA, NA, NA, NA, NA, No, NA…
$ Smoke100 <fct> Yes, Yes, Yes, NA, Yes, NA, NA, No, No, No, Yes…
$ Smoke100n <fct> Smoker, Smoker, Smoker, NA, Smoker, NA, NA, Non…
$ SmokeAge <int> 18, 18, 18, NA, 38, NA, NA, NA, NA, NA, 13, NA,…
$ Marijuana <fct> Yes, Yes, Yes, NA, Yes, NA, NA, Yes, Yes, Yes, …
$ AgeFirstMarij <int> 17, 17, 17, NA, 18, NA, NA, 13, 13, 13, NA, 19,…
$ RegularMarij <fct> No, No, No, NA, No, NA, NA, No, No, No, NA, Yes…
$ AgeRegMarij <int> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 20,…
$ HardDrugs <fct> Yes, Yes, Yes, NA, Yes, NA, NA, No, No, No, No,…
$ SexEver <fct> Yes, Yes, Yes, NA, Yes, NA, NA, Yes, Yes, Yes, …
$ SexAge <int> 16, 16, 16, NA, 12, NA, NA, 13, 13, 13, 17, 22,…
$ SexNumPartnLife <int> 8, 8, 8, NA, 10, NA, NA, 20, 20, 20, 15, 7, 100…
$ SexNumPartYear <int> 1, 1, 1, NA, 1, NA, NA, 0, 0, 0, NA, 1, 1, NA, …
$ SameSex <fct> No, No, No, NA, Yes, NA, NA, Yes, Yes, Yes, No,…
$ SexOrientation <fct> Heterosexual, Heterosexual, Heterosexual, NA, H…
$ PregnantNow <fct> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
$ gender <dbl> 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1,…
Data exploratie
Onderzoeksvraag: hoe verschilt de lengte van volwassen mannen en vrouwen.
- We pipen de dataset naar de function
filter om de data te filteren volgens leeftijd.
- We plotten de lengte metingen.
- We selecteren de data data met het commando
ggplot(aes(x=lengte))
- We voegen een histogram toe met het commando
geom_histogram()
- We maken twee vertikale panels met het commando
facet_grid(Gender~.)
- We veranderen het label van de x-as met de
xlab functie.
NHANES%>%
filter(Age > 18 & !is.na(Height)) %>%
ggplot(aes(x = Height))+
geom_histogram() +
facet_grid(Gender ~ .) +
xlab("Lengte (cm)")

We zien dat de data nu min of meer symmetrisch verdeeld zijn en een klokvorm hebben.
Dat zal ons toe laten om de data verder samen te vatten door gebruik te maken van twee statistieken: het gemiddelde en de standaard deviatie wat een maat is voor de spreiding van de gegevens rond het gemiddelde.
We maken nu een subset van de data die we zullen gebruiken om aan te tonen hoe de variabiliteit in kleine steekproeven kan variëren van steekproef tot steekproef.
- We filteren op leeftijd en verwijderen ontbrekenden gegevens (NA, Not Available).
- We selecteren enkel het geslacht en Lengte zodat de dataset geen onnodige variabelen bevat.
nhanesSub <- NHANES %>%
filter(Age > 25 & !is.na(Height)) %>%
select(c("Gender","Height"))
We berekenen het gemiddelde en de standaard deviatie voor de lengte voor mannen en vrouwen in de grote dataset. We groeperen de data hiervoor op basis van het geslacht (variable Gender).
HeightSum <- nhanesSub %>%
group_by(Gender) %>%
summarize_at("Height",
list(mean = mean,
sd = sd)
)
knitr::kable(
HeightSum %>%
mutate_if(is.numeric, round, digits=1)
)
| female |
161.9 |
7.2 |
| male |
175.8 |
7.5 |
Experiment
Stel dat we geen toegang hebben tot de metingen van de NHANES studie.
We zouden dan een experiment op moeten zetten om metingen bij mannen en vrouwen te doen.
Veronderstel dat we budget hebben om metingen bij 5 mannen en 5 vrouwen te doen.
We zouden dan 5 mannen en 5 vrouwen boven de 25 jaar at random selecteren uit de Amerikaanse populatie.
We kunnen dit experiment simuleren door 5 vrouwen en 5 mannen at random te selecteren uit de NHANES studie.
set.seed(1000001)
nSamp <- 5
fem <- nhanesSub %>%
filter(Gender=="female") %>%
sample_n(size=5)
mal <- nhanesSub %>%
filter(Gender=="male") %>%
sample_n(size=5)
samp1 <- rbind(fem,mal)
samp1
# A tibble: 10 x 2
Gender Height
<fct> <dbl>
1 female 159.
2 female 168.
3 female 157.
4 female 155.
5 female 163.
6 male 178.
7 male 173.
8 male 187.
9 male 173.
10 male 185.
Data Exploratie
samp1 %>%
ggplot(aes(x=Height)) +
geom_histogram() +
facet_grid(Gender~.) +
xlab("Lengte (cm)")

HeightSumExp1 <- samp1 %>%
group_by(Gender) %>%
summarize_at("Height",
list(mean = mean,
sd = sd)
)
HeightSumExp1
# A tibble: 2 x 3
Gender mean sd
<fct> <dbl> <dbl>
1 female 161. 5.17
2 male 179. 6.49
Histogram is niet zinvol als we maar zo weinig datapunten hebben.
Boxplot is beter:

We voeren hier ook een t-test uit.
t.test(Height~Gender,data=samp1)
Welch Two Sample t-test
data: Height by Gender
t = -4.9713, df = 7.6177, p-value = 0.001261
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
-27.068985 -9.811015
sample estimates:
mean in group female mean in group male
160.62 179.06
In het experiment zijn vrouwen zijn gemiddeld 18.44 cm kleiner dan mannen. En als we een statistische test uitvoeren (zie hoofdstuk 5: Statistische besluitvorming) kunnen we besluiten dat dit verschil statistisch significant is.
Herhaal het experiment
Als we het experiment herhalen selecteren we andere mensen en verkrijgen we andere resultaten.
fem <- nhanesSub %>%
filter(Gender=="female") %>%
sample_n(size=5)
mal <- nhanesSub %>%
filter(Gender=="male") %>%
sample_n(size=5)
samp2 <- rbind(fem,mal)
HeightSumExp2 <- samp2 %>%
group_by(Gender) %>%
summarize_at("Height",
list(mean=mean,
sd=sd)
)
HeightSumExp2
# A tibble: 2 x 3
Gender mean sd
<fct> <dbl> <dbl>
1 female 169. 9.38
2 male 175. 6.12
samp2 %>%
ggplot(aes(x = Gender,y = Height)) +
geom_boxplot(outlier.shape = NA) +
geom_point(position = "jitter") +
geom_point(
aes(x = 1, y = HeightSumExp1$mean[1]),
size = 3,
pch = 17,
color="darkred") +
geom_point(
aes(x = 2, y = HeightSumExp1$mean[1]),
size = 3,
pch = 17,
color = "darkred") +
ylab("Height (cm)")

t.test(Height ~ Gender, data=samp2)
Welch Two Sample t-test
data: Height by Gender
t = -1.1379, df = 6.8813, p-value = 0.2932
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
-17.586435 6.186435
sample estimates:
mean in group female mean in group male
169.06 174.76
In de nieuwe steekproef zijn vrouwen zijn gemiddeld 5.7 cm kleiner dan mannen. En dit verschil is statistisch niet significant
Herhaal het experiment opnieuw
seed <- 1336602
fem <- nhanesSub %>%
filter(Gender=="female") %>%
sample_n(size=5)
mal <- nhanesSub %>%
filter(Gender=="male") %>%
sample_n(size=5)
samp3 <- rbind(fem,mal)
HeightSumExp3 <- samp3 %>%
group_by(Gender) %>%
summarize_at("Height",
list(mean=mean,
sd=sd)
)
HeightSumExp3
# A tibble: 2 x 3
Gender mean sd
<fct> <dbl> <dbl>
1 female 162. 12.5
2 male 170. 14.5
samp3 %>%
ggplot(aes(x = Gender,y = Height)) +
geom_boxplot(outlier.shape = NA) +
geom_point(position = "jitter") +
geom_point(
aes(x = 1, y = HeightSumExp1$mean[1]),
size = 3,
pch = 17,
color="darkred") +
geom_point(
aes(x = 2, y = HeightSumExp1$mean[1]),
size = 3,
pch = 17,
color = "darkred") +
ylab("Height (cm)")

t.test(Height ~ Gender, data=samp3)
Welch Two Sample t-test
data: Height by Gender
t = -0.99138, df = 7.8343, p-value = 0.3511
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
-28.34441 11.34441
sample estimates:
mean in group female mean in group male
161.96 170.46
In de nieuwe steekproef zijn vrouwen gemiddeld 8.5 cm kleiner dan mannen. En dit verschil is statistisch niet significant
Samenvatting
We trokken at random andere proefpersonen in elke steekproef
Hierdoor verschillen lengtemetingen van steekproef tot steekproef.
Dus ook de geschatte gemiddeldes en standaard deviaties.
Bijgevolg zijn onze conclusies ook onzeker en kunnen deze wijzigen van steekproef tot steekproef.
Steekproeven waarbij het effect tegengesteld is aan dat in de populatie en waarbij we besluiten dat het verschil significant is, zijn zeldzaam.
\(\rightarrow\) Met statistiek controleren we de kans op het trekken foute conclusies.
- Dit wordt in de onderstaande code geïllustreerd. We trekken 10000 herhaalde steekproeven van 5 vrouwen en 5 mannen uit de NHANES studie.
# Aantal simulaties en steekproefgrootte per groep
nSim <- 10000
nSamp <- 5
# We filteren de data vooraf zodat we dit niet telkens opnieuw hoeven te doen
fem <- nhanesSub %>%
filter(Gender == "female")
mal <- nhanesSub %>%
filter(Gender == "male")
# Simulatie studie
# Om snelle functies te kunnen gebruiken nemen we eerst nSim steekproeven en berekenen we daarna alles.
femSamps <- malSamps <-matrix(NA, nrow=nSamp, ncol=nSim)
for (i in 1:nSim)
{
femSamps[,i] <- sample(fem$Height, nSamp)
malSamps[,i] <- sample(mal$Height, nSamp)
}
res <- data.frame(
verschil=colMeans(femSamps) - colMeans(malSamps),
Rfast::ttests(femSamps, malSamps)
)
sum(res$pvalue < 0.05 & res$verschil < 0)
[1] 7148
[1] 2852
sum(res$pvalue < 0.05 & res$verschil>0)
[1] 0
res %>%
ggplot(aes(x=verschil,y=-log10(pvalue),color=pvalue < 0.05)) +
geom_point() +
xlab("Gemiddeld Verschil (cm)") +
ylab("Statistische Significantie (-log10 p)")

res %>%
ggplot(aes(y = verschil)) +
geom_boxplot() +
ylab("Gemiddeld Verschil (cm)")

$x
[1] ""
attr(,"class")
[1] "labels"
Op basis van 10 000 steekproeven van 5 mannen en 5 vrouwen zagen we dat in 7148 steekproeven vrouwen gemiddeld significant kleiner zijn dan mannen. In 2852 steekproeven besluiten we dat vrouwen en mannen gemiddeld niet significant verschillen in lengte. En in 0 besluiten we dat vrouwen gemiddeld significant groter zijn dan mannen.
- De steekproef die we toonden waaruit we zouden besluiten dat vrouwen significant groter zijn dan mannen is heel onwaarschijnlijk. Er moesten 1336602 steekproeven worden getrokken om deze extreme steekproef te vinden.
Het feit dat we in veel steekproeven resultaten vinden die statistisch niet significant zijn komt omdat de statistische toets een te lage kracht heeft om het verschil te detecteren wanneer er maar 5 observaties zijn per groep.
Grotere steekproef?
Wat gebeurt er als we de steekproef verhogen naar 50 observaties per groep?
# Aantal simulaties en steekproefgrootte per groep
nSim <- 10000
nSamp <- 50
# We filteren de data vooraf zodat we dit niet telkens opnieuw hoeven te doen
fem <- nhanesSub %>%
filter(Gender == "female")
mal <- nhanesSub %>%
filter(Gender == "male")
# Simulatie studie
# Om snelle functies te kunnen gebruiken nemen we eerst nSim steekproeven en berekenen we daarna alles.
femSamps <- malSamps <- matrix(NA, nrow = nSamp, ncol = nSim)
for (i in 1:nSim)
{
femSamps[,i] <- sample(fem$Height, nSamp)
malSamps[,i] <- sample(mal$Height, nSamp)
}
res <- data.frame(
verschil = colMeans(femSamps) - colMeans(malSamps),
Rfast::ttests(femSamps, malSamps)
)
sum(res$pvalue < 0.05 & res$verschil < 0)
[1] 10000
[1] 0
sum(res$pvalue < 0.05 & res$verschil > 0)
[1] 0
res %>%
ggplot(aes(x=verschil,y=-log10(pvalue),color=pvalue<0.05)) +
geom_point() +
xlab("Gemiddeld Verschil (cm)") +
ylab("Statistische Significantie (-log10 p)")

res %>%
ggplot(aes(y=verschil)) +
geom_boxplot() +
ylab("Gemiddeld Verschil (cm)")

$x
[1] ""
attr(,"class")
[1] "labels"
LS0tCnRpdGxlOiAiMS4gSW50cm9kdWN0aWU6IFdhYXJvbSBTdGF0aXN0aWVrPyIKYXV0aG9yOiAiTGlldmVuIENsZW1lbnQiCmRhdGU6ICJzdGF0T21pY3MsIEdoZW50IFVuaXZlcnNpdHkgKGh0dHBzOi8vc3RhdG9taWNzLmdpdGh1Yi5pbykiCm91dHB1dDoKICAgIGh0bWxfZG9jdW1lbnQ6CiAgICAgIGNvZGVfZG93bmxvYWQ6IHRydWUgICAgCiAgICAgIHRoZW1lOiBjb3NtbwogICAgICB0b2M6IHRydWUKICAgICAgdG9jX2Zsb2F0OiB0cnVlCiAgICAgIGhpZ2hsaWdodDogdGFuZ28KICAgICAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlCi0tLQoKIyBJbnRyb2R1Y3RpZQoKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CmtuaXRyOjpvcHRzX2NodW5rJHNldChpbmNsdWRlID0gVFJVRSwgY29tbWVudCA9IE5BLCBlY2hvID0gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UgPSBGQUxTRSwgd2FybmluZyA9IEZBTFNFKQpsaWJyYXJ5KHRpZHl2ZXJzZSkKYGBgCgotIFdlIGxldmVuIGluIGhldCBiaWcgZGF0YSBlcmEKLSBHZWdldmVucyBvdmVyIGxvY2F0aWUsIHN1cmZnZWRyYWcsIGFhbmtvb3BnZWRyYWcsIHNvY2lhbGUgbWVkaWEKLSBXZXRlbnNjaGFwOiBleHByZXNzaWUgbWV0ZW4gdmFuIGR1aXplbmRlbiBnZW5lbiwgZWl3aXR0ZW4sLi4uIHZvb3IgZWxrIHN1YmplY3QKLSBDaGVtaXNjaGUgcHJvY2VzIGNvbnRyb2xlOiBncm9vdCBhYW50YWwgc2Vuc29yZW4gZGllIGNvbnRpbnUgZWVuIHByb2NlcyBtZXRlbiB6b2RhdCBoZXQgcHJvY2VzIGthbiB3b3JkZW4gYmlqZ2VzdHV1cmQKLSBEYXRhIGRyaXZlbiBqb3VybmFsaXNtCi0gLi4uCgpTdGF0aXN0aWVrIGlzIGRlIHdldGVuc2NoYXAgb20gdGUgbGVyZW4gdWl0IGVtcGlyaXNjaGUgZ2VnZXZlbnMKClN0YXRpc3Rpc2NoZSBnZWxldHRlcmRoZWlkIGlzIGNydWNpYWFsIG9tIHJlc3VsdGF0ZW4gZW4gcHVibGljYXRpZXMga3JpdGlzY2ggdGUga3VubmVuIGludGVycHJldGVyZW4uCgojIyBCb3V0YWRlOiBNZXQgc3RhdGlzdGllayBrYW4gamUgYWxsZXMgYmV3aWp6ZW4KCi0tLQoKIyMgTWV0IGZvdXRlIHN0YXRpc3RpZWsga2FuIGplIGFsbGVzIGJld2lqemVuCgotLS0KCkdhcmNpYS1CZXJ0aG91ICYgQWxjYXJheiAoTWVkLiBSZXMuIE1ldGguIDIwMDQpOgoKLSBKYWFyZ2FuZyAyMDAxIHZhbiBOYXR1cmUgZW4gQnJpdGlzaCBNZWRpY2FsIEpvdXJuYWwKLSAzOCUgZW4gMjUlIHZhbiBhcnRpa2VsZW4gYmV2YXQgZWVuIHN0YXRpc3Rpc2NoZSBmb3V0Ci0gMTElOiBmb3V0ZW4gdGVnZW4gaW50ZXJwcmV0YXRpZQotIDQlOiBiZXNsdWl0IHNwcmVla3QgZXZpZGVudGllIHRlZ2VuCgotLS0KCiFbXShodHRwczovL2dpdGh1Yi5jb20vc3RhdE9taWNzL3NiYzIwL3Jhdy9tYXN0ZXIvdGhlb3J5L2ZpZ3VyZXMvcG5hc0h1bWFuTW91c2VQYXBlclRpdGxlLnBuZyl7d2lkdGg9OTUlfQoKInRoZSBleHByZXNzaW9uIGZvciBtYW55IHNldHMgb2YgZ2VuZXMgd2FzIGZvdW5kIHRvIGJlIG1vcmUgc2ltaWxhciBpbiBkaWZmZXJlbnQgdGlzc3VlcyB3aXRoaW4gdGhlIHNhbWUgc3BlY2llcyB0aGFuIGJldHdlZW4gc3BlY2llcy4iCgoiT3ZlcmFsbCwgb3VyIHJlc3VsdHMgaW5kaWNhdGUgdGhhdCB0aGVyZSBpcyBjb25zaWRlcmFibGUgUk5BIGV4cHJlc3Npb24gZGl2ZXJzaXR5IGJldHdlZW4gaHVtYW5zIGFuZCBtaWNlLCB3ZWxsIGJleW9uZCB3aGF0IHdhcyBkZXNjcmliZWQgcHJldmlvdXNseSwgbGlrZWx5IHJlZmxlY3RpbmcgdGhlIGZ1bmRhbWVudGFsIHBoeXNpb2xvZ2ljYWwgZGlmZmVyZW5jZXMgYmV0d2VlbiB0aGVzZSB0d28gb3JnYW5pc21zLiIKCi0tLQoKIVtdKGh0dHBzOi8vcGJzLnR3aW1nLmNvbS9tZWRpYS9DRHNTemNVVkFBQVZYc2s/Zm9ybWF0PXBuZyZuYW1lPTkwMHg5MDApCmh0dHBzOi8vdHdpdHRlci5jb20vWV9HaWxhZC9zdGF0dXMvNTkzMDg4NDUxNDYyOTYzMjAyCgotLS0KCiFbXShodHRwczovL3Bicy50d2ltZy5jb20vbWVkaWEvQ0RzU3pjRlVNQUFWd0dhP2Zvcm1hdD1wbmcmbmFtZT1zbWFsbCkKaHR0cHM6Ly90d2l0dGVyLmNvbS9ZX0dpbGFkL3N0YXR1cy81OTMwODg0NTE0NjI5NjMyMDIKCi0tLQoKCiMgT2tzZWwgbWljcm9iaW9tZSB2b29yYmVlbGQKCgohW10oaHR0cHM6Ly9pbWFnZXMudnJ0LmJlL3dpZHRoMTI4MC8yMDE4LzA2LzI3LzRlNzIwOThkLTdhMGQtMTFlOC1hYmNjLTAyYjdiNzZiZjQ3Zi5qcGcpe3dpZHRoPTcwJX0KCi0gaHR0cHM6Ly93d3cudnJ0LmJlL3ZydG53cy9ubC8yMDE4LzEwLzIyL2dlem9jaHQtbWVuc2VuLW1ldC1wZW5ldHJhbnRlLWxpamZnZXVyLW9tLXByb2Jpb3Rpc2NoZS1kZW9kb3IvCi0gaHR0cHM6Ly95b3V0dS5iZS85UklGeXFMWGRWdwoKLS0tCgotIE9rc2VsZ2V1ciB3b3JkdCBuaWV0IHZlcm9vcnphYWt0IGRvb3IgaGV0IHp3ZWV0IHplbGYuIERlIGdldXIgaXMgYWZrb21zdGlnIHZhbiBzcGVjaWZpY2llayBtaWNyby1vcmdhbmlzbWVuIHZhbiBkZSBncm9lcCAqQ29yeW5lYmFjdGVyaXVtIHNwcC4qIGRpZSBoZXQgendlZXQgbWV0YWJvbGlzZXJlbi4gKlN0YXBoeWxvY29jY3VzIHNwcC4qIHppam4gZWVuIGFuZGVyZSBncm9lcCBiYWN0ZXJpw6tuIGRpZSBvb2sgYWJ1bmRhbnQgemlqbiBpbiBoZXQgbWljcm9iaW9tZSB2YW4gZGUgb2tzZWwgZGllIHp3ZWV0IG1ldGFib2xpc2VyZW4gbmFhciBtZXRhYm9saWV0ZW4gZGllIG5pZXQgc3Rpbmtlbi4KCi0gRGUgQ01FVC1ncm9lcCBhYW4gVUdFTlQgZG9ldCBvbmRlcnpvZWsgbmFhciBoZXQgdHJhbnNwbGFudGVyZW4gdmFuIGRlIG1pY3JvYmnDq2xlIGdlbWVlbnNjaGFwLCBoZXQgbWljcm9iaW9tZSwgb20gbWVuc2VuIHZhbiBnZXVyZW5kZSBva3NlbHMgYWYgdGUgaGVscGVuLiAgCgotIFZvb3JnZXN0ZWxkZSB0aGVyYXBpZQogIAkxLiBWZXJ3aWpkZXIgaGV0IG9rc2VsIG1pY3JvYmlvbWUgbWV0IGFudGliaW90aWNhCiAgICAyLiBCZcOvbnZsb2VkIGhldCBva3NlbCBtaWNyb2Jpb21lIGRvb3IgbWljcm9iaW9tZSB0ZSB0cmFuc3BsYW50ZXJlbiB2YW4gZWVuIGluZGl2aWR1ZSBkaWUgZ2VlbiBnZXVyZW5kZSBva3NlbHMgaGVlZnQgKGh0dHBzOi8veW91dHUuYmUvOVJJRnlxTFhkVncpCgoKLS0tCgojIyBQcm9lZm9wemV0IChleHBlcmltZW50YWwgZGVzaWduKQoKYGBge3Igb3V0LndpZHRoPSc4MCUnLGZpZy5hc3A9LjgsIGZpZy5hbGlnbj0nY2VudGVyJyxlY2hvPUZBTFNFfQppZiAoInBpIiVpbiVscygpKSBybSgicGkiKQprb3B2b2V0ZXI8LWZ1bmN0aW9uKHgseSxhbmdsZT0wLGw9LjIsY2V4LmRvdD0uNSxwY2g9MTksY29sPSJibGFjayIpCnsKYW5nbGU9YW5nbGUvMTgwKnBpCnBvaW50cyh4LHksY2V4PWNleC5kb3QscGNoPXBjaCxjb2w9Y29sKQpsaW5lcyhjKHgseCtsKmNvcygtcGkvMithbmdsZSkpLGMoeSx5K2wqc2luKC1waS8yK2FuZ2xlKSksY29sPWNvbCkKbGluZXMoYyh4K2wvMipjb3MoLXBpLzIrYW5nbGUpLHgrbC8yKmNvcygtcGkvMithbmdsZSkrbC80KmNvcyhhbmdsZSkpLGMoeStsLzIqc2luKC1waS8yK2FuZ2xlKSx5K2wvMipzaW4oLXBpLzIrYW5nbGUpK2wvNCpzaW4oYW5nbGUpKSxjb2w9Y29sKQpsaW5lcyhjKHgrbC8yKmNvcygtcGkvMithbmdsZSkseCtsLzIqY29zKC1waS8yK2FuZ2xlKStsLzQqY29zKHBpK2FuZ2xlKSksYyh5K2wvMipzaW4oLXBpLzIrYW5nbGUpLHkrbC8yKnNpbigtcGkvMithbmdsZSkrbC80KnNpbihwaSthbmdsZSkpLGNvbD1jb2wpCmxpbmVzKGMoeCtsKmNvcygtcGkvMithbmdsZSkseCtsKmNvcygtcGkvMithbmdsZSkrbC8yKmNvcygtcGkvMitwaS80K2FuZ2xlKSksYyh5K2wqc2luKC1waS8yK2FuZ2xlKSx5K2wqc2luKC1waS8yK2FuZ2xlKStsLzIqc2luKC1waS8yK3BpLzQrYW5nbGUpKSxjb2w9Y29sKQpsaW5lcyhjKHgrbCpjb3MoLXBpLzIrYW5nbGUpLHgrbCpjb3MoLXBpLzIrYW5nbGUpK2wvMipjb3MoLXBpLzItcGkvNCthbmdsZSkpLGMoeStsKnNpbigtcGkvMithbmdsZSkseStsKnNpbigtcGkvMithbmdsZSkrbC8yKnNpbigtcGkvMi1waS80K2FuZ2xlKSksY29sPWNvbCkKfQoKcGFyKG1hcj1jKDAsMCwwLDApLG1haT1jKDAsMCwwLDApKQpwbG90KDAsMCx4bGFiPSIiLHlsYWI9IiIseGxpbT1jKDAsMTApLHlsaW09YygwLDEwKSxjb2w9MCx4YXh0PSJub25lIix5YXh0PSJub25lIixheGVzPUZBTFNFKQpyZWN0KDAsNiwxMCwxMCxib3JkZXI9InJlZCIsbHdkPTIpCnRleHQoLjUsOCwicG9wdWxhdGlvbiIsc3J0PTkwLGNvbD0icmVkIixjZXg9MikKc3ltYm9scyAoMywgOCwgY2lyY2xlcz0xLjUsIGNvbD0icmVkIixhZGQ9VFJVRSxmZz0icmVkIixpbmNoZXM9RkFMU0UsbHdkPTIpCnNldC5zZWVkKDMzMCkKZ3JpZD1zZXEoMCwxLjMsLjAxKQoKZm9yIChpIGluIDE6NTApCnsKCWFuZ2xlMT1ydW5pZihuPTEsbWluPTAsbWF4PTM2MCkKCWFuZ2xlMj1ydW5pZihuPTEsbWluPTAsbWF4PTM2MCkKCXJhZGl1cz1zYW1wbGUoZ3JpZCxwcm9iPWdyaWReMipwaS9zdW0oZ3JpZF4yKnBpKSxzaXplPTEpCglrb3B2b2V0ZXIoMytyYWRpdXMqY29zKGFuZ2xlMS8xODAqcGkpLDgrcmFkaXVzKnNpbihhbmdsZTEvMTgwKnBpKSxhbmdsZT1hbmdsZTIpCn0KdGV4dCg3LjUsOCwiTWljcm9iaW9tZSBpbiBwb3B1bGF0aW9uIixjb2w9InJlZCIsY2V4PTEuMikKYGBgCgotLS0KCgpgYGB7ciBvdXQud2lkdGg9JzgwJScsZmlnLmFzcD0uOCwgZmlnLmFsaWduPSdjZW50ZXInLGVjaG89RkFMU0V9CmlmICgicGkiJWluJWxzKCkpIHJtKCJwaSIpCmtvcHZvZXRlcjwtZnVuY3Rpb24oeCx5LGFuZ2xlPTAsbD0uMixjZXguZG90PS41LHBjaD0xOSxjb2w9ImJsYWNrIikKewphbmdsZT1hbmdsZS8xODAqcGkKcG9pbnRzKHgseSxjZXg9Y2V4LmRvdCxwY2g9cGNoLGNvbD1jb2wpCmxpbmVzKGMoeCx4K2wqY29zKC1waS8yK2FuZ2xlKSksYyh5LHkrbCpzaW4oLXBpLzIrYW5nbGUpKSxjb2w9Y29sKQpsaW5lcyhjKHgrbC8yKmNvcygtcGkvMithbmdsZSkseCtsLzIqY29zKC1waS8yK2FuZ2xlKStsLzQqY29zKGFuZ2xlKSksYyh5K2wvMipzaW4oLXBpLzIrYW5nbGUpLHkrbC8yKnNpbigtcGkvMithbmdsZSkrbC80KnNpbihhbmdsZSkpLGNvbD1jb2wpCmxpbmVzKGMoeCtsLzIqY29zKC1waS8yK2FuZ2xlKSx4K2wvMipjb3MoLXBpLzIrYW5nbGUpK2wvNCpjb3MocGkrYW5nbGUpKSxjKHkrbC8yKnNpbigtcGkvMithbmdsZSkseStsLzIqc2luKC1waS8yK2FuZ2xlKStsLzQqc2luKHBpK2FuZ2xlKSksY29sPWNvbCkKbGluZXMoYyh4K2wqY29zKC1waS8yK2FuZ2xlKSx4K2wqY29zKC1waS8yK2FuZ2xlKStsLzIqY29zKC1waS8yK3BpLzQrYW5nbGUpKSxjKHkrbCpzaW4oLXBpLzIrYW5nbGUpLHkrbCpzaW4oLXBpLzIrYW5nbGUpK2wvMipzaW4oLXBpLzIrcGkvNCthbmdsZSkpLGNvbD1jb2wpCmxpbmVzKGMoeCtsKmNvcygtcGkvMithbmdsZSkseCtsKmNvcygtcGkvMithbmdsZSkrbC8yKmNvcygtcGkvMi1waS80K2FuZ2xlKSksYyh5K2wqc2luKC1waS8yK2FuZ2xlKSx5K2wqc2luKC1waS8yK2FuZ2xlKStsLzIqc2luKC1waS8yLXBpLzQrYW5nbGUpKSxjb2w9Y29sKQp9CgpwYXIobWFyPWMoMCwwLDAsMCksbWFpPWMoMCwwLDAsMCkpCnBsb3QoMCwwLHhsYWI9IiIseWxhYj0iIix4bGltPWMoMCwxMCkseWxpbT1jKDAsMTApLGNvbD0wLHhheHQ9Im5vbmUiLHlheHQ9Im5vbmUiLGF4ZXM9RkFMU0UpCnJlY3QoMCw2LDEwLDEwLGJvcmRlcj0icmVkIixsd2Q9MikKdGV4dCguNSw4LCJwb3B1bGF0aW9uIixzcnQ9OTAsY29sPSJyZWQiLGNleD0yKQpzeW1ib2xzICgzLCA4LCBjaXJjbGVzPTEuNSwgY29sPSJyZWQiLGFkZD1UUlVFLGZnPSJyZWQiLGluY2hlcz1GQUxTRSxsd2Q9MikKc2V0LnNlZWQoMzMwKQpncmlkPXNlcSgwLDEuMywuMDEpCgpmb3IgKGkgaW4gMTo1MCkKewoJYW5nbGUxPXJ1bmlmKG49MSxtaW49MCxtYXg9MzYwKQoJYW5nbGUyPXJ1bmlmKG49MSxtaW49MCxtYXg9MzYwKQoJcmFkaXVzPXNhbXBsZShncmlkLHByb2I9Z3JpZF4yKnBpL3N1bShncmlkXjIqcGkpLHNpemU9MSkKCWtvcHZvZXRlcigzK3JhZGl1cypjb3MoYW5nbGUxLzE4MCpwaSksOCtyYWRpdXMqc2luKGFuZ2xlMS8xODAqcGkpLGFuZ2xlPWFuZ2xlMikKfQp0ZXh0KDcuNSw4LCJNaWNyb2Jpb21lIGluIHBvcHVsYXRpb24iLGNvbD0icmVkIixjZXg9MS4yKQoKcmVjdCgwLDAsMTAsNCxib3JkZXI9ImJsdWUiLGx3ZD0yKQp0ZXh0KC41LDIsInNhbXBsZSIsc3J0PTkwLGNvbD0iYmx1ZSIsY2V4PTIpCnN5bWJvbHMgKDMsIDIsIGNpcmNsZXM9MS41LCBjb2w9InJlZCIsYWRkPVRSVUUsZmc9ImJsdWUiLGluY2hlcz1GQUxTRSxsd2Q9MikKZm9yIChpIGluIDA6MSkKCWZvciAoaiBpbiAwOjQpCnsKCglrb3B2b2V0ZXIoMi4xK2oqKDMuOS0yLjEpLzQsMS4xK2kvMixjb2w9ImJsYWNrIikKfQpmb3IgKGkgaW4gMjozKQoJZm9yIChqIGluIDA6NCkKewoKCWtvcHZvZXRlcigyLjEraiooMy45LTIuMSkvNCwxLjYraS8yLGNvbD0iYmxhY2siKQp9CnRleHQoNy41LDIsIk1pY3JvYmlvbWUgaW4gc2FtcGxlIixjb2w9ImJsdWUiLGNleD0xLjIpCgphcnJvd3MoMyw1LjksMyw0LjEsY29sPSJibGFjayIsbHdkPTMpCnRleHQoMS41LDUsIkVYUC4gREVTSUdOICgxKSIsY29sPSJibGFjayIsY2V4PTEuMikKYGBgCgotLS0KCi0gRXhwZXJpbWVudDoKCiAgICAtIDIwIHBlcnNvbmVuIHdvcmRlbiBhdCByYW5kb20gdWl0IGRlIHBvcHVsYXRpZSBnZXRyb2trZW4gdmFuIHBlcnNvbmVuIG1ldCBlZW4gb2tzZWxnZXVyOiBzdGVla3Byb2VmIHJlcHJlc2VudGF0aWVmIHZvb3IgcG9wdWxhdGllIQoKICAgIC0gZGUgcGVyc29uZW4gd29yZGVuIGF0IHJhbmRvbSB2ZXJkZWVsZCBvdmVyIHR3ZWUgYmVoYW5kZWxpbmdzZ3JvZXBlbjoKCiAgICAgICAgLSBwbGFjZWJvIChlbmtlbCBhbnRpYmlvdGljYSkKICAgICAgICAtIHRyYW5zcGxhbnRpZSAoYW50aWJpb3RpY2EgZW4gbWljcm9iacOrbGUgdHJhbnNwbGFudGF0aWUpLgogICAgICAgIC0gUmFuZG9taXNhdGllIGlzIGJlbGFuZ3Jpamsgb20gZXJ2b29yIHRlIHpvcmdlbiBkYXQgZGUgZ3JvZXBlbiB2ZXJnZWxpamtiYWFyIHppam4uCgogICAgLSBIZXQgbWljcm9iaW9tZSB3b3JkdCBiZW1vbnN0ZXJkIDYgd2VrZW4gbmEgZGUgYmVoYW5kZWxpbmcuCiAgICAtIFRoZSByZWxhdGl2ZSBhYnVuZGFudGllIHZhbiAqU3RhcGh5bG9jb2NjdXMgc3BwLiogb3AgKkNvcnluZWJhY3Rlcml1bSBzcHAuKiArICpTdGFwaHlsb2NvY2N1cyBzcHAuKiBpbiBoZXQgbWljcm9iaW9tZSB3b3JkdCBnZW1ldGVuIHZpYSBER0dFICgqRGVuYXR1cmluZyBHcmFkaWVudCBHZWwgRWxlY3Ryb3Bob3Jlc2lzKikuCgotLS0KCkRHR0UKCiFbXShodHRwczovL2pvdXJuYWxzLnBsb3Mub3JnL3Bsb3NvbmUvYXJ0aWNsZS9maWd1cmUvaW1hZ2U/c2l6ZT1sYXJnZSZkb3dubG9hZD0maWQ9MTAuMTM3MS9qb3VybmFsLnBvbmUuMDA3MDUzOC5nMDAxKXt3aWR0aD03MCV9CgpodHRwczovL2RvaS5vcmcvMTAuMTM3MS9qb3VybmFsLnBvbmUuMDA3MDUzOAoKLS0tCgpWZXJ0YWFsIG9uZGVyem9la3N2cmFhZyBuYWFyIGlldHMgd2F0IHdlIGt1bm5lbiBxdWFudGlmaWNlcmVuOiBJcyBlciBlZW4gdmVyc2NoaWwgaW4gcmVsYXRpZXZlIGFidW5kYW50aWUgdmFuICpTdGFwaHlsb2NvY2N1cyBzcHAuKiBpbiBoZXQgbWljcm9iaW9tZSB2YW4gZGUgcGxhY2VibyBncm9lcCBlbiBkZSB0cmFuc3BsYW50YXRpZQoKLS0tCgpgYGB7ciBvdXQud2lkdGg9JzgwJScsZmlnLmFzcD0uOCwgZmlnLmFsaWduPSdjZW50ZXInLGVjaG89RkFMU0V9CmlmICgicGkiJWluJWxzKCkpIHJtKCJwaSIpCmtvcHZvZXRlcjwtZnVuY3Rpb24oeCx5LGFuZ2xlPTAsbD0uMixjZXguZG90PS41LHBjaD0xOSxjb2w9ImJsYWNrIikKewphbmdsZT1hbmdsZS8xODAqcGkKcG9pbnRzKHgseSxjZXg9Y2V4LmRvdCxwY2g9cGNoLGNvbD1jb2wpCmxpbmVzKGMoeCx4K2wqY29zKC1waS8yK2FuZ2xlKSksYyh5LHkrbCpzaW4oLXBpLzIrYW5nbGUpKSxjb2w9Y29sKQpsaW5lcyhjKHgrbC8yKmNvcygtcGkvMithbmdsZSkseCtsLzIqY29zKC1waS8yK2FuZ2xlKStsLzQqY29zKGFuZ2xlKSksYyh5K2wvMipzaW4oLXBpLzIrYW5nbGUpLHkrbC8yKnNpbigtcGkvMithbmdsZSkrbC80KnNpbihhbmdsZSkpLGNvbD1jb2wpCmxpbmVzKGMoeCtsLzIqY29zKC1waS8yK2FuZ2xlKSx4K2wvMipjb3MoLXBpLzIrYW5nbGUpK2wvNCpjb3MocGkrYW5nbGUpKSxjKHkrbC8yKnNpbigtcGkvMithbmdsZSkseStsLzIqc2luKC1waS8yK2FuZ2xlKStsLzQqc2luKHBpK2FuZ2xlKSksY29sPWNvbCkKbGluZXMoYyh4K2wqY29zKC1waS8yK2FuZ2xlKSx4K2wqY29zKC1waS8yK2FuZ2xlKStsLzIqY29zKC1waS8yK3BpLzQrYW5nbGUpKSxjKHkrbCpzaW4oLXBpLzIrYW5nbGUpLHkrbCpzaW4oLXBpLzIrYW5nbGUpK2wvMipzaW4oLXBpLzIrcGkvNCthbmdsZSkpLGNvbD1jb2wpCmxpbmVzKGMoeCtsKmNvcygtcGkvMithbmdsZSkseCtsKmNvcygtcGkvMithbmdsZSkrbC8yKmNvcygtcGkvMi1waS80K2FuZ2xlKSksYyh5K2wqc2luKC1waS8yK2FuZ2xlKSx5K2wqc2luKC1waS8yK2FuZ2xlKStsLzIqc2luKC1waS8yLXBpLzQrYW5nbGUpKSxjb2w9Y29sKQp9CgpwYXIobWFyPWMoMCwwLDAsMCksbWFpPWMoMCwwLDAsMCkpCnBsb3QoMCwwLHhsYWI9IiIseWxhYj0iIix4bGltPWMoMCwxMCkseWxpbT1jKDAsMTApLGNvbD0wLHhheHQ9Im5vbmUiLHlheHQ9Im5vbmUiLGF4ZXM9RkFMU0UpCnJlY3QoMCw2LDEwLDEwLGJvcmRlcj0icmVkIixsd2Q9MikKdGV4dCguNSw4LCJwb3B1bGF0aW9uIixzcnQ9OTAsY29sPSJyZWQiLGNleD0yKQpzeW1ib2xzICgzLCA4LCBjaXJjbGVzPTEuNSwgY29sPSJyZWQiLGFkZD1UUlVFLGZnPSJyZWQiLGluY2hlcz1GQUxTRSxsd2Q9MikKc2V0LnNlZWQoMzMwKQpncmlkPXNlcSgwLDEuMywuMDEpCgpmb3IgKGkgaW4gMTo1MCkKewoJYW5nbGUxPXJ1bmlmKG49MSxtaW49MCxtYXg9MzYwKQoJYW5nbGUyPXJ1bmlmKG49MSxtaW49MCxtYXg9MzYwKQoJcmFkaXVzPXNhbXBsZShncmlkLHByb2I9Z3JpZF4yKnBpL3N1bShncmlkXjIqcGkpLHNpemU9MSkKCWtvcHZvZXRlcigzK3JhZGl1cypjb3MoYW5nbGUxLzE4MCpwaSksOCtyYWRpdXMqc2luKGFuZ2xlMS8xODAqcGkpLGFuZ2xlPWFuZ2xlMikKfQp0ZXh0KDcuNSw4LCJNaWNyb2Jpb21lIGluIHBvcHVsYXRpb24iLGNvbD0icmVkIixjZXg9MS4yKQoKcmVjdCgwLDAsMTAsNCxib3JkZXI9ImJsdWUiLGx3ZD0yKQp0ZXh0KC41LDIsInNhbXBsZSIsc3J0PTkwLGNvbD0iYmx1ZSIsY2V4PTIpCnN5bWJvbHMgKDMsIDIsIGNpcmNsZXM9MS41LCBjb2w9InJlZCIsYWRkPVRSVUUsZmc9ImJsdWUiLGluY2hlcz1GQUxTRSxsd2Q9MikKZm9yIChpIGluIDA6MSkKCWZvciAoaiBpbiAwOjQpCnsKCglrb3B2b2V0ZXIoMi4xK2oqKDMuOS0yLjEpLzQsMS4xK2kvMixjb2w9InB1cnBsZSIpCn0KZm9yIChpIGluIDI6MykKCWZvciAoaiBpbiAwOjQpCnsKCglrb3B2b2V0ZXIoMi4xK2oqKDMuOS0yLjEpLzQsMS42K2kvMixjb2w9Im9yYW5nZSIpCn0KdGV4dCg3LjUsMiwiTWljcm9iaW9tZSBpbiBzYW1wbGUiLGNvbD0iYmx1ZSIsY2V4PTEuMikKCmFycm93cygzLDUuOSwzLDQuMSxjb2w9ImJsYWNrIixsd2Q9MykKdGV4dCgxLjUsNSwiRVhQLiBERVNJR04gKDEpIixjb2w9ImJsYWNrIixjZXg9MS4yKQp0ZXh0KDcuNSwuNSwiREFUQSBFWFBMT1JBVElPTiAmXG5ERVNDUklQVElWRSBTVEFUSVNUSUNTICgyKSIsY29sPSJibGFjayIsY2V4PTEuMikKYGBgCgotLS0KCiMjIERhdGEgRXhwbG9yYXRpZSBlbiBiZXNjaHJpanZlbmRlIHN0YXRpc3RpZWsKCgotIERhdGEgZXhwbG9yYXRpZSBpcyBoZWVsIGJlbGFuZ3Jpamsgb20gaW56aWNodCB0ZSBrcmlqZ2VuIGluIGRlIGRhdGEgZW4gaXMgZWVuIGVzc2VudGnDq2xlIGVlcnN0ZSBzdGFwIG9tIHRlIGxlcmVuIHVpdCBkYXRhLgotIEhldCB3b3JkdCB2YWFrIG9uZGVyZ2V3YWFyZGVlcmQgb2Ygb3ZlciBoZXQgaG9vZmQgZ2V6aWVuLgoKLS0tCgojIyMgSW1wb3J0ZWVyIGRlIGRhdGEKCi0gRGF0YSBpbiBkZXplIGN1cnN1cyB3b3JkdCB2ZXJ3ZXJrdCB2aWEgaGV0IHN0YXRpc3Rpc2NoIHNvZnR3YXJlIHBha2tldCBSLgotIERpdCBwYWtrZXQgbGFhdCB0b2Ugb20gdGUgbGVyZW4gdWl0IGRhdGEuCi0gSW4gZGV6ZSBjdXJzdXMgZ2FhbiB3ZSBkYXRhIGVlcnN0IGV4cGxvcmVyZW4gb20gaW56aWNodCB0ZSB2ZXJ3ZXJ2ZW4gaW4gZGUgZ2VnZXZlbnMgb20gZGllIHZlcnZvbGdlbnMgc3RhdGlzdGlzY2ggdGUgdmVyd2Vya2VuLgotIFZvb3JhbGVlciB3ZSBoaWVybWVlIHZhbiBzdGFydCBrdW5uZW4gZ2FhbiBtb2V0ZW4gd2UgZGUgZGF0YSBlZXJzdCBpbXBvcnRlcmVuIGluIFIuCgotIFZpYSBoZXQgdm9sZ2VuZGUgY29tbWFuZG8ga3VubmVuIHdlIGVua2VsZSByZWdlbHMgdmFuIGVlbiBkYXRhIGJlc3RhbmQgaW5sZXplbiBvbSBkZSBzdHJ1Y3R1dXIgdmFuIGhldCBkYXRhIGJlc3RhbmQgdGUgd2V0ZW4gdGUga29tZW4uCgpgYGB7cn0KcmVhZF9saW5lcygiaHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL3N0YXRPbWljcy9zYmMyMC9tYXN0ZXIvZGF0YS9hcm1waXQuY3N2IikKYGBgCgotIEdlZ2V2ZW5zIGluIGhldCBiZXN0YW5kIHppam4gZG9vciBjb21tYSdzIGdlc2NoZWlkZW4uCi0gRWxrZSByaWogYmV2YXQgZGUgZ2VnZXZlbnMgdm9vciAxIHByb2VmcGVyc29vbgotIFZlcnNjaGlsbGVuZGUgdmFyaWFiZWxlbiB3b3JkZW4gZ2VtZXRlbiBwZXIgcGVyc29vbiBlbiB6aWpuIHZhbiBlbGthYXIgZ2VzY2hlaWRlbiBkb29yIGVlbiBjb21tYS4gSGV0IGJlc3RhbmQgaXMgY3N2IGZvcm1hYXQ6ICJjb21tYSBzZXBhcmF0ZWQgdmFsdWVzIi4KLSBXZSBrdW5uZW4gYmVzdGFuZGVuIG1ldCBkaXQgZm9ybWFhdCBpbmxlemVuIFIgdmlhIGhldCBjb21tYW5kbyByZWFkX2Nzdi4KLSBXZSBzbGFhbiBkZSBkYXRhIG9wIGluIFIgaW4gaGV0IG9iamVjdCBtZXQgbmFhbSBhcC4gSGllcnZvb3IgZ2VicnVpa2VuIHdlIGRlIGA8LWAgb3BlcmF0b3IuCi0gV2UgZ2V2ZW4gZGUgZGF0YSB0YWJlbCB0ZXJ1ZyBkb29yIGhldCBvYmplY3QgYWFuIHRlIHJvZXBlbiBkb29yIHppam4gbmFhbSB0ZSB0eXBlbi4KCmBgYHtyfQphcCA8LSByZWFkX2NzdigiaHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL3N0YXRPbWljcy9zYmMyMC9tYXN0ZXIvZGF0YS9hcm1waXQuY3N2IikKYXAKYGBgCgotLS0KCiMjIyBCZXNjaHJpanZlbmRlIHN0YXRpc3RpZWsKCi0gSW4gYXJ0aWtlbHMgZW4gZGUgbWVkaWEgd29yZGVuIHJlc3VsdGF0ZW4gdWl0IGVlbiBzdGVla3Byb2VmIHZhYWsgZ2VyYXBwb3J0ZWVyZCBhLmQuaC52LiBnZW1pZGRlbGRlIGVuIGRlIHN0YW5kYWFyZGFmd2lqa2luZwoKLSBXZSB2YXR0ZW4gZGUgZGF0YSBlZXJzdCBzYW1lbi4gV2UgYmVyZWtlbmVuIGhldCBnZW1pZGRlbGRlIGVuIGRlIHN0YW5kYWFyZCBkZXZpYXRpZSAoZWVuIG1hYXQgdm9vciBkZSBzcHJlaWRpbmcsIHppZSB2b2xnZW5kZSBob29mZHN0dWtrZW4pLgpXZSBzbGFhbiBoZXQgcmVzdWx0YWF0IGhpZXJ2YW4gb3AgaW4gaGV0IG9iamVjdCBhcFJlbFN1bSB2aWEgYGFwUmVsU3VtIDwtYC4KCjEuIFdlIHBpcGVuICh2aWEgYCU+JWApIGhldCBgYXBgIGRhdGFmcmFtZSBuYWFyIGRlIGBncm91cF9ieWAgZnVuY3RpZSBvbSBkZSBkYXRhIHRlIGdyb2VwZXJlbiBwZXIgdHJlYXRtZW50IHRydDogYGdyb3VwX2J5KHRydClgLgoKMi4gV2UgcGlwZW4gaGV0IHJlc3VsdGFhdCBuYWFyIGRlIGBzdW1tYXJpemVfYXRgIGZ1bmN0aW9uIG9tIGRlICJyZWwiIHZhcmlhYmxlIHNhbWVuIHRlIHZhdHRlbiBlbiBiZXJla2VuZW4gaGllcmJpaiBoZXQgZ2VtaWRkZWxkZSBlbiBzdGFuZGFhcmRhZndpamtpbmcuIE9tZGF0IHdlIGRlIGRhdGEgZWVyc3QgaGViYmVuIGdlZ3JvZXBlZXJkIHp1bGxlbiB3ZSBoZXQgZ2VtaWRkZWxkZSBlbiBkZSBzdGFuZGFhcmQgZGV2aWF0aWUgYmVyZWtlbmVuIHBlciBncm9lcC4KCgoKYGBge3J9CmFwUmVsU3VtIDwtIGFwICU+JQogIGdyb3VwX2J5KHRydCkgJT4lCiAgc3VtbWFyaXplX2F0KCJyZWwiLAogICAgICAgICAgICAgICBsaXN0KG1lYW49bWVhbiwKICAgICAgICAgICAgICAgICAgICBzZD1zZAogICAgICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgICkKYGBgCgpXZSB0b25lbiB2ZXJ2b2xnZW5zIGhldCByZXN1bHRhYXQgZG9vciBoZXQgb2JqZWN0IGFwUmVsU3VtIGFhbiB0ZSByb2VwZW4KCmBgYHtyfQphcFJlbFN1bQpgYGAKCldlIGt1bm5lbiBvb2sgZWVuIHRhYmVsIGluIGRlIHdlYnBhZ2luYSBvZiBoZXQgcGRmIGJlc3RhbmQgaW50ZWdyZXJlbiB2aWEgaGV0IGNvbW1hbmRvIGthYmxlIHZhbiBoZXQga25pdHIgcGFra2V0OgoKYGBge3J9CmtuaXRyOjprYWJsZShhcFJlbFN1bSkKYGBgCgotLS0KCiMjIyBHcmFmaWVrZW4KCldlIG1ha2VuIGluIGRlemUgY3Vyc3VzIGdlYnJ1aWsgdmFuIGhldCBwYWtrZXQgYGdncGxvdDJgIG9tIGdyYWZpZWtlbiB0ZSBtYWtlbi4gIApNZXQgZGUgZ2dwbG90MiBiaWJsaW90aGVlayBrdW5uZW4gd2UgZ2VtYWtrZWxpamsgZ3JhZmlla2VuIG9wYm91d2VuIGluIGxhZ2VuIChsYXllcnMpLgpIaWVyZG9vciBsZWVzdCBkZSBjb2RlIHZlZWwgbWFra2VsaWprZXIuCgojIyMjIGJhcnBsb3QKCkJhciBwbG90cyB3b3JkZW4gaGVlbCB2ZWVsIGdlYnJ1aWt0IGluIGFydGlrZWxzIG9tIHJlc3VsdGF0ZW4gd2VlciB0ZSBnZXZlbi4KCjEuIFdlIHBpcGVuIGRlIHNhbWVuZ2V2YXR0ZSBkYXRhIG5hYXIgZGUgZnVuY3RpZSBgZ2dwbG90YC4gRGF0IGlzIGRlIGJhc2lzIHZhbiBlbGtlIGdncGxvdC4gIFdlIHNlbGVjdGVyZW4gZGUgdmFyaWFiZWxlIG1ldCBkZSBiZWhhbmRlbGluZyB0cnQgYWxzIHggdmFyaWFiZWxlIGVuIGRlIHZhcmlhYmVsZSBtZXQgbmFhbSBtZWFuIGFscyB5LXZhcmlhYmVsZSB2b29yIGRlIHBsb3QuCldlIGRvZW4gZGl0IHN0ZWVkcyB2aWEgZGUgYWVzdGV0aWNzIGBhZXNgIGZ1bmN0aWUuICAgYGFlcyh4PXRydCx5PW1lYW4pYAoKMi4gV2UgbWFrZW4gZWVuIGJhcnBsb3QgZG9vciBlZW4gbGFhZyB0b2UgdGUgdm9lZ2VuIHZpYSBkZSAgYGdlb21fYmFyYCBmdW5jdGlvbi4gRGUgc3RhdGlzdGllayBpcyBgc3RhdD0iaWRlbnRpdHkiYCBvbWRhdCBkZSBob29ndGUgdmFuIGRlIGJhciBnZWxpamsgaXMgYWFuIGRlIHdhYXJkZSB2b29yIHkgKGhpZXIgaGV0IGdlbWlkZGVsZGUgdm9vciBkZSByZWxhdGlldmUgYWJ1bmRhbnRpZSkuCgozLiBXZSB2b2VnZW4gZm91dGVudmxhZ2dlbiB0b2Ugb20gZGUgb256ZWtlcmhlaWQgb3AgaGV0IGdlbWlkZGVsZGUgd2VlciB0ZSBnZXZlbi4gIFdlIGRvZW4gZGl0IHZpYSBkZSBgZ2VvbV9lcnJvcmJhcmAgZnVuY3RpZSBlbiBzcGVjaWZpw6tyZW4gaGV0IG1pbmltdW0gZW4gbWF4aW11bSB2YW4gZGUgZXJyb3IgYmFyLiBIZXQgYHdpZHRoYCBhcmd1bWVudCB3b3JkdCBnZWJydWlrdCBvbSBkZSBicmVlZHRlIHZhbiBkZSBlcnJvciBiYXIgc21hbGxlciB0ZSBtYWtlbiBkYXQgZGV6ZSB2YW4gZGUgYmFyLgoKYGBge3J9CmFwUmVsU3VtICU+JQogIGdncGxvdChhZXMoeD10cnQseT1tZWFuKSkgKwogIGdlb21fYmFyKHN0YXQ9ImlkZW50aXR5IikgKwogIGdlb21fZXJyb3JiYXIoYWVzKHltaW49bWVhbi1zZCx5bWF4PW1lYW4rc2QpLHdpZHRoPS4yKQpgYGAKCi0gSXMgZGV6ZSBwbG90IGluZm9ybWF0aWVmPz8KCi0tLQoKIyMjIyBib3hwbG90cwoKQmFycGxvdHMgemlqbiBnZWVuIGdvZWRlIGdyYWZpZWtlbjoKCi0gWmUgemlqbiBuaWV0IGluZm9ybWF0aWVmCgotIFplIHZpc3VsYXJpc2VyZW4gZWVuIHNhbWVudmF0dGluZyB2YW4gZGUgZGF0YSBkb29yIHR3ZWUgcHVudGVuOiBgdHdvIHBvaW50IHN1bW1hcnlgOiBnZW1pZGRlbGRlIGVuIGRlIHN0YW5kYWFyZCBkZXZpYXRpZSBoaWVyb3AgZW4ga3VubmVuIGJldGVyIGluIGVlbiB0YWJlbCB3b3JkZW4gb3BnZW5vbWVuLgoKLSBaZSBsYXRlbiBuaWV0IHRvZSBvbSBhbm9tYWxpZcOrbiBpbiBkZSBkYXRhIHpvYWxzIG1lZXRmb3V0ZW4gb3AgdGUgc3BvcmVuLgoKLSBaZSB2ZXJicnVpa2VuIHZlZWwgcnVpbXRlLCBiLnYuIHZhbiBudWwgdG90IGRlIGtsZWluc3RlIHdhYXJkZSB2b29yIGRlIHJlbGF0aWV2ZSBhYnVuZGFudGllKSB3YWFyIGdlZW4gZGF0YSBpbiBsaWd0LgoKSGV0IGlzIGJldGVyIG9tIGRlIGRhdGEgem8gcnV3IG1vZ2VsaWprIHZvb3IgdGUgc3RlbGxlbiB6b2RhdCB3ZSBpbnppY2h0IGtyaWpnZW4gaW4gZGUgdmVyZGVsaW5nIHZhbiBkZSBnZWdldmVucy4KSGllcnZvb3IgenVsbGVuIHdlIG9uZGVybWVlciBib3hwbG90cyBnZWJydWlrZW4uCgotLS0KCiMjIyMgQm94cGxvdHMKCmBgYHtyIGZpZy5hbGlnbj0nY2VudGVyJyxlY2hvPUZBTFNFfQpmZW0gPC0gTkhBTkVTOjpOSEFORVMgJT4lIGZpbHRlcihHZW5kZXI9PSJmZW1hbGUiICYgIWlzLm5hKEhlaWdodCkgJiBBZ2U+MTgpICU+JSBzZWxlY3QoSGVpZ2h0KQpib3hwbG90KGZlbSRIZWlnaHQsIHlsYWI9Imxlbmd0ZSAoY20pIixjZXgubGFiPTEuNSxjZXguYXhpcz0xLjUsY2V4Lm1haW49MS41KQpyYW5nZUw8LXF1YW50aWxlKGZlbSRIZWlnaHQsYyguMjUsLjc1KSkrYygtMSwxKSpkaWZmKHF1YW50aWxlKGZlbSRIZWlnaHQsYyguMjUsLjc1KSkpKjEuNQpib3hZczwtYyhyYW5nZUxbMV0rKG1pbihmZW0kSGVpZ2h0KS1yYW5nZUxbMV0pLzIscmFuZ2UoZmVtJEhlaWdodFtmZW0kSGVpZ2h0PD1yYW5nZUxbMl0mZmVtJEhlaWdodD49cmFuZ2VMWzFdXSkscXVhbnRpbGUoZmVtJEhlaWdodCxjKC4yNSwuNSwuNzUpKSxyYW5nZUxbMl0rKG1heChmZW0kSGVpZ2h0KS1yYW5nZUxbMl0pLzIpCnRleHQoYygwLjUscmVwKDEuMyw1KSwwLjUpLGJveFlzLGxhYmVscz1jKCJvdXRsaWVycyIsIndpc2tlciIsIndpc2tlciIsIngyNSIsIm1lZGlhYW4iLCJ4NzUiLCJvdXRsaWVycyIpLHBvcz00LGNleD0xLjMpCmxpbmVzKGMoMC45LC43LDAuNywwLjkpLGMocmFuZ2VMWzJdLHJhbmdlTFsyXSsobWF4KGZlbSRIZWlnaHQpLXJhbmdlTFsyXSkvMixyYW5nZUxbMl0rKG1heChmZW0kSGVpZ2h0KS1yYW5nZUxbMl0pLzIsbWF4KGZlbSRIZWlnaHQpKSxsdHk9MikKbGluZXMoYygwLjksLjcsMC43LDAuOSksYyhyYW5nZUxbMV0scmFuZ2VMWzFdKyhtaW4oZmVtJEhlaWdodCktcmFuZ2VMWzFdKS8yLHJhbmdlTFsxXSsobWluKGZlbSRIZWlnaHQpLXJhbmdlTFsxXSkvMixtaW4oZmVtJEhlaWdodCkpLGx0eT0yKQpgYGAKCi0tLQoKV2UgbWFrZW4gbnUgZWVuIGJveHBsb3Qgdm9vciBkZSBhcCBkYXRhCgoxLiBXZSBwaXBlbiBoZXQgYGFwYCBkYXRhZnJhbWUgbmFhciBgZ2dwbG90YAoyLiBXZSBzZWxlY3RlcmVuIGRlIGRhdGEgdm9vciBkZSBwbG90IHZpYSBgZ2dwbG90KGFlcyh4PXRydCx5PXJlbCkpYAozLiBXZSB2b2VnZW4gbGFhZyB0b2Ugdm9vciBkZSBib3hwbG90IGRtdiBkZSBmdW5jdGllIGBnZW9tX2JveHBsb3QoKWAKCmBgYHtyfQphcCAlPiUgIAogIGdncGxvdChhZXMoeD10cnQseT1yZWwpKSArCiAgZ2VvbV9ib3hwbG90KCkKYGBgCgoKLS0tCgpNZXJrIG9wIGRhdCB3ZSBkZSBwbG90IG9vayBvcCBrdW5uZW4gc2xhYW4gYWxzIGVlbiBvYmplY3QuCgpgYGB7cn0KYXBCb3hwbG90IDwtIGFwICU+JSAgCiAgZ2dwbG90KGFlcyh4PXRydCx5PXJlbCkpICsKICBnZW9tX2JveHBsb3QoKQpgYGAKCkRlIHBsb3Qgd29yZHQgZGFuIG5pZXQgZ2VtYWFrdC4KCk9tIGRlIHBsb3Qgd2VlciB0ZSBnZXZlbiBrdW5uZW4gd2UgaGV0IG9iamVjdCBhYW5yb2VwZW4KCmBgYHtyfQphcEJveHBsb3QKYGBgCgotLS0KCi0gTWVyayBvcCBkYXQgd2UgbmlldCB6b3ZlZWwgZ2VnZXZlbnMgaGViYmVuLiBFbmtlbCAxMCBwZXIgZ3JvZXAuCgotIEhldCBpcyBhbHRpamQgYmV0ZXIgb20gZGUgZGF0YSB6byBydXcgbW9nZWxpamsgdGUgdG9uZW4hCgpPbWRhdCBlciBuaWV0IHpvdmVlbCBnZWdldmVucyB6aWpuIGt1bm5lbiB3ZSBkZSBkYXRhIHRvZXZvZWdlbiBhYW4gZGUgcGxvdCB6b25kZXIgZGF0IGRpZSB0ZSBkcnVrIHdvcmR0LgoKLSBNZXJrIG9wIGRhdCB3ZSBoZXQgYXJndW1lbnQgYG91dGxpZXIuc2hhcGVgIG9wIE5BIChub3QgYXZhaWxhYmxlKSB6ZXR0ZW4gYG91dGxpZXIuc2hhcGU9TkFgIGluIHRoZSBgZ2VvbV9ib3hwbG90YCBmdW5jdGllIG9tZGF0IHdlIGFuZGVycyBvdXRsaWVycyB0d2VlIGtlZXIgd2VlciB6dWxsZW4gZ2V2ZW4uIEVlcnN0IHZpYSBkZSBib3hwbG90IGxhYWcgZW4gZGFhcm5hIG9tZGF0IHdlIGVlbiBsYWFnIG1ldCBhbGxlIHJ1d2UgZGF0YSB0b2V2b2VnZW4gYWFuIGRlIHBsb3QuCi0gV2UgZ2V2ZW4gZGUgcnV3ZSBkYXRhIHdlZXIgdmlhIGRlICBgZ2VvbV9wb2ludChwb3NpdGlvbj0iaml0dGVyIilgIGZ1bmN0aWUuIFdlIGdlYnJ1aWtlbiBoaWVyYmlqIGhldCBhcmd1bWVudCBwb3NpdGlvbj0naml0dGVyJyB6b2RhdCB3ZSB3YXQgcmFuZG9tIHJ1aXMgdG9ldm9lZ2VuIGFhbiBkZSB4LWNvcmRpbmFhdCB6b2RhdCBkZSBnZWdldmVucyBlbGthYXIgbmlldCBvdmVybGFwcGVuLgoKYGBge3J9CmFwICU+JSAgCiAgZ2dwbG90KGFlcyh4PXRydCx5PXJlbCkpICsKICBnZW9tX2JveHBsb3Qob3V0bGllci5zaGFwZT1OQSkgKwogIGdlb21fcG9pbnQocG9zaXRpb249ImppdHRlciIpCmBgYAoKRGl0IGlzIGVlbiBpbmZvcm1hdGlldmUgcGxvdCEKCi0tLQoKQWFuZ2V6aWVuIHdlIGRlIHBsb3Qgb29rIGhlYmJlbiBvcGdlc2xhZ2VuIGtvbmRlbiB3ZSBkaXQgb29rIGRvZW4gZG9vciBkZSBwbG90IG9wIHRlIHJvZXBlbiBlbiBub2cgZWVuIGxhYWcgdG9lIHRlIHZvZWdlbi4KCmBgYHtyfQphcEJveHBsb3QgKwogIGdlb21fcG9pbnQocG9zaXRpb249ImppdHRlciIpCmBgYAoKV2UgaGFkZGVuIGhldCByZXN1bHRhYXQgb29rIG9wbmlldXcgb3Aga3VubmVuIHNsYWFuIHZvb3IgbGF0ZXIgaGVyZ2VicnVpay4KCmBgYHtyfQphcEJveHBsb3QgPC0gYXBCb3hwbG90ICsKICBnZW9tX3BvaW50KHBvc2l0aW9uPSJqaXR0ZXIiKQpgYGAKCi0tLQoKLSBXZSB6YWdlbiBkdWlkZWxpamsgZWVuIGVmZmVjdCB2YW4gZGUgdHJhbnNwbGFudGF0aWUgb3AgZGUgcmVsYXRpZXZlIGFidW5kYW50aWUgdmFuIFN0YXBoeWxvY29jY3VzLgoKLSBJcyBkYXQgZWZmZWN0IG51IGdyb290IGdlbm9lZyBvbSB0ZSBrdW5uZW4gY29uY2x1ZGVyZW4gZGF0IGRlIGJlaGFuZGVsaW5nIHdlcmt0PwoKLS0tCgpgYGB7ciBvdXQud2lkdGg9JzgwJScsZmlnLmFzcD0uOCwgZmlnLmFsaWduPSdjZW50ZXInLGVjaG89RkFMU0V9CmlmICgicGkiJWluJWxzKCkpIHJtKCJwaSIpCmtvcHZvZXRlcjwtZnVuY3Rpb24oeCx5LGFuZ2xlPTAsbD0uMixjZXguZG90PS41LHBjaD0xOSxjb2w9ImJsYWNrIikKewphbmdsZT1hbmdsZS8xODAqcGkKcG9pbnRzKHgseSxjZXg9Y2V4LmRvdCxwY2g9cGNoLGNvbD1jb2wpCmxpbmVzKGMoeCx4K2wqY29zKC1waS8yK2FuZ2xlKSksYyh5LHkrbCpzaW4oLXBpLzIrYW5nbGUpKSxjb2w9Y29sKQpsaW5lcyhjKHgrbC8yKmNvcygtcGkvMithbmdsZSkseCtsLzIqY29zKC1waS8yK2FuZ2xlKStsLzQqY29zKGFuZ2xlKSksYyh5K2wvMipzaW4oLXBpLzIrYW5nbGUpLHkrbC8yKnNpbigtcGkvMithbmdsZSkrbC80KnNpbihhbmdsZSkpLGNvbD1jb2wpCmxpbmVzKGMoeCtsLzIqY29zKC1waS8yK2FuZ2xlKSx4K2wvMipjb3MoLXBpLzIrYW5nbGUpK2wvNCpjb3MocGkrYW5nbGUpKSxjKHkrbC8yKnNpbigtcGkvMithbmdsZSkseStsLzIqc2luKC1waS8yK2FuZ2xlKStsLzQqc2luKHBpK2FuZ2xlKSksY29sPWNvbCkKbGluZXMoYyh4K2wqY29zKC1waS8yK2FuZ2xlKSx4K2wqY29zKC1waS8yK2FuZ2xlKStsLzIqY29zKC1waS8yK3BpLzQrYW5nbGUpKSxjKHkrbCpzaW4oLXBpLzIrYW5nbGUpLHkrbCpzaW4oLXBpLzIrYW5nbGUpK2wvMipzaW4oLXBpLzIrcGkvNCthbmdsZSkpLGNvbD1jb2wpCmxpbmVzKGMoeCtsKmNvcygtcGkvMithbmdsZSkseCtsKmNvcygtcGkvMithbmdsZSkrbC8yKmNvcygtcGkvMi1waS80K2FuZ2xlKSksYyh5K2wqc2luKC1waS8yK2FuZ2xlKSx5K2wqc2luKC1waS8yK2FuZ2xlKStsLzIqc2luKC1waS8yLXBpLzQrYW5nbGUpKSxjb2w9Y29sKQp9CgpwYXIobWFyPWMoMCwwLDAsMCksbWFpPWMoMCwwLDAsMCkpCnBsb3QoMCwwLHhsYWI9IiIseWxhYj0iIix4bGltPWMoMCwxMCkseWxpbT1jKDAsMTApLGNvbD0wLHhheHQ9Im5vbmUiLHlheHQ9Im5vbmUiLGF4ZXM9RkFMU0UpCnJlY3QoMCw2LDEwLDEwLGJvcmRlcj0icmVkIixsd2Q9MikKdGV4dCguNSw4LCJwb3B1bGF0aW9uIixzcnQ9OTAsY29sPSJyZWQiLGNleD0yKQpzeW1ib2xzICgzLCA4LCBjaXJjbGVzPTEuNSwgY29sPSJyZWQiLGFkZD1UUlVFLGZnPSJyZWQiLGluY2hlcz1GQUxTRSxsd2Q9MikKc2V0LnNlZWQoMzMwKQpncmlkPXNlcSgwLDEuMywuMDEpCgpmb3IgKGkgaW4gMTo1MCkKewoJYW5nbGUxPXJ1bmlmKG49MSxtaW49MCxtYXg9MzYwKQoJYW5nbGUyPXJ1bmlmKG49MSxtaW49MCxtYXg9MzYwKQoJcmFkaXVzPXNhbXBsZShncmlkLHByb2I9Z3JpZF4yKnBpL3N1bShncmlkXjIqcGkpLHNpemU9MSkKCWtvcHZvZXRlcigzK3JhZGl1cypjb3MoYW5nbGUxLzE4MCpwaSksOCtyYWRpdXMqc2luKGFuZ2xlMS8xODAqcGkpLGFuZ2xlPWFuZ2xlMikKfQp0ZXh0KDcuNSw4LCJNaWNyb2Jpb21lIGluIHBvcHVsYXRpb24iLGNvbD0icmVkIixjZXg9MS4yKQoKcmVjdCgwLDAsMTAsNCxib3JkZXI9ImJsdWUiLGx3ZD0yKQp0ZXh0KC41LDIsInNhbXBsZSIsc3J0PTkwLGNvbD0iYmx1ZSIsY2V4PTIpCnN5bWJvbHMgKDMsIDIsIGNpcmNsZXM9MS41LCBjb2w9InJlZCIsYWRkPVRSVUUsZmc9ImJsdWUiLGluY2hlcz1GQUxTRSxsd2Q9MikKZm9yIChpIGluIDA6MSkKCWZvciAoaiBpbiAwOjQpCnsKCglrb3B2b2V0ZXIoMi4xK2oqKDMuOS0yLjEpLzQsMS4xK2kvMixjb2w9InB1cnBsZSIpCn0KZm9yIChpIGluIDI6MykKCWZvciAoaiBpbiAwOjQpCnsKCglrb3B2b2V0ZXIoMi4xK2oqKDMuOS0yLjEpLzQsMS42K2kvMixjb2w9Im9yYW5nZSIpCn0KdGV4dCg3LjUsMiwiTWljcm9iaW9tZSBpbiBzYW1wbGUiLGNvbD0iYmx1ZSIsY2V4PTEuMikKCmFycm93cygzLDUuOSwzLDQuMSxjb2w9ImJsYWNrIixsd2Q9MykKdGV4dCgxLjUsNSwiRVhQLiBERVNJR04gKDEpIixjb2w9ImJsYWNrIixjZXg9MS4yKQp0ZXh0KDcuNSwuNSwiREFUQSBFWFBMT1JBVElPTiAmXG5ERVNDUklQVElWRSBTVEFUSVNUSUNTICgyKSIsY29sPSJibGFjayIsY2V4PTEuMikKYXJyb3dzKDcsNC4xLDcsNS45LGNvbD0iYmxhY2siLGx3ZD0zKQp0ZXh0KDguNSw1LCJFU1RJTUFUSU9OICZcbklORkVSRU5DRSAoMykiLGNvbD0iYmxhY2siLGNleD0xLjIpCmBgYAoKLS0tCgotIEluZHVjdGllOiBEb29yIG1pZGRlbCB2YW4gc3RhdGlzdGlzY2hlIGJlc2x1aXR2b3JtaW5nIChpbmZlcmVuY2UpIGt1bm5lbiB3ZSB1aXRzcHJha2VuIGRvZW4gb3ZlciBkZSBwb3B1bGF0aWUgb3AgYmFzaXMgdmFuIGVlbiBzdGVla3Byb2VmLgoKLSBEZSBwcmlqcyBkaWUgd2UgaGllcnZvb3IgYmV0YWxlbiBpcyBvbnpla2VyaGVpZCEKCi0gV2Uga3VubmVuIG9wIGJhc2lzIHZhbiBlZW4gc3RlZWtwcm9lZiBub29pdCBhYnNvbHV1dCB6ZWtlciB6aWpuIHZhbiBvbnplIGNvbmNsdXNpZXMuCgotLS0KCi0gTWV0IGRhdGEga3VubmVuIHdlIG5pZXQgYmV3aWp6ZW4gZGF0IGVlbiBiZWhhbmRlbGluZyB3ZXJrdC4KCi0gRmFsc2lmaWNhdGllIHByaW5jaXBlIHZhbiBQb3BwZXI6IERhdGEga3VubmVuIGVua2VsIGVlbiBoeXBvdGhlc2Ugb2YgZWVuIHRoZW9yaWUgb250a3JhY2h0ZW4uCgotIE1ldCBzdGF0aXN0aWVrIGt1bm5lbiB3ZSBkdXMgbmlldCBhYW50b25lbiBkYXQgZGUgYmVoYW5kZWxpbmcgd2Vya3QuCgotIFN0YXRpc3RpZWsgemFsIG9ucyB3ZWwgdG9lbGF0ZW4gb20gaGV0IG9tZ2VrZWVyZGUgdGUgZmFsc2lmacOrcmVuOiBhbHMgd2UgdmVyb25kZXJzdGVsbGVuIGRhdCBlciBnZWVuIGVmZmVjdCB2YW4gZGUgYmVoYW5kZWxpbmcsIHNwcmVla3QgZGUgZGF0YSBpbiBkZSBzdGVla3Byb2VmIGRpdCB0ZWdlbj8KCi0gTWV0IHN0YXRpc3RpZWsga3VubmVuIHdlIGJlcmVrZW5lbiBob2Ugd2FhcnNjaGlqbmxpamsgaGV0IGlzIG9tIGVlbiBnZW1pZGRlbGQgdmVyc2NoaWwgaW4gcmVsYXRpZXZlIGFidW5kYW50aWUgdGUgemllbiB0dXNzZW4gcGxhY2VibyBlbiB0cmFuc3BsYW50YXRpZWdyb2VwIGRhdCBtaW5zdGVucyB6byBncm9vdCBpcyBhbHMgaW4gZGUgc3RlZWtwcm9lZiBhbHMgZGUgYmVoYW5kZWxpbmcgZ2VlbiBlZmZlY3Qgem91IGhlYmJlbi4KCi0gRGllIGthbnMgd29yZHQgZWVuIHAtd2FhcmRlIGdlbm9lbWQuCgotIEFscyBwIGhlZWwga2xlaW4gaXMsIGRhbiBpcyBoZXQgaGVlbCBvbndhYXJzY2hpam5saWprIG9tIGVlbiBkZXJnZWxpamsgZWZmZWN0IHRlIG9ic2VydmVyZW4gaW4gZWVuIHN0ZWVrcHJvZWYgZG9vciB0b2V2YWwuCgotIHAgd29yZHQgbWVlc3RhbCB2ZXJnZWxla2VuIG1ldCA1JS4gQWxzIGVyIGdlZW4gZWZmZWN0IGlzIHZhbiBkZSBiZWhhbmRlbGluZyBkYW4gdG9sZXJlcmVuIDUlIHZhbHMgcG9zaXRpZXZlIGNvbmNsdXNpZXMuCgotIE9tIGRlIGthbnMgcCB0ZSBiZXJla2VuZW4gaXMgaGV0IG5vZGlnIG9tIGRlIGRhdGEgdGUgbW9kZWxsZXJlbiBtZXQgc3RhdGlzdGlzY2hlIG1vZGVsbGVuLgoKLS0tCgpJbiBsYXRlcmUgaG9vZmRzdHVra2VuIHp1bGxlbiB3ZSB6aWVuIGRhdCB3ZSB0LXRlc3Qga3VubmVuIGdlYnJ1aWtlbiBvbSBoZXRnZWVuIHdlIG9ic2VydmVyZW4gaW4gZGUgbWljcm9iaW9tZSBkYXRhc2V0IHRlIHZlcmFsZ2VtZW5lbiBuYWFyIGRlIHBvcHVsYXRpZS4KCmBgYHtyfQphcCAlPiUgdC50ZXN0KHJlbH50cnQsZGF0YT0uKQpgYGAKCkNvbmNsdXNpZToKR2VtaWRkZWxkIGlzIGRlIHJlbGF0aWV2ZSBhYnVuZGFudGllIHZhbiBTdGFwaHlsb2NvY2N1cyBpbiBoZXQgbWljcm9iaW9tZSB2YW4gcGVyc29uZW4gbWV0IGVlbiB6d2VldGdldXIgYHIgZm9ybWF0KGFwUmVsU3VtJG1lYW5bMl0tYXBSZWxTdW0kbWVhblsxXSxkaWdpdHM9MylgJSBob2dlciBuYSBkZSB0cmFuc3BsYW50aWUgZGFuIG5hIGRlIHBsYWNlYm8gYmVoYW5kZWxpbmcuCgotLS0KCiMjIFJhbmRvbWlzYXRpZQoKLSBXYXQgd29yZHQgemlqbiBkZSBjb25zZXF1ZW50aWVzIHZhbiBoZXQgZ2VicnVpayB2YW4gZWVuIHN0ZWVrcHJvZWYgZW4gdmFuIHJhbmRvbWlzYXRpZT8KCi0gUmFuZG9taXNhdGllIGlzIHN0ZXJrIGdlcmVsYXRlZXJkIG1ldCBoZXQgY29uY2VwdCB2YW4gZGUgcG9wdWxhdGllIGVuIHNjb3BlIHZhbiBkZSBzdHVkaWUuICAKCi0gRGUgc2NvcGUgdmFuIGRlIHN0dWRpZSBtb2V0IGdvZWQgd29yZGVuIG9tc2NocmV2ZW4gdm9vciBkZSBzdGFydCB2YW4gaGV0IGV4cGVyaW1lbnQuCgotIE9tZGF0IGRlIHN0YXRpc3Rpc2NoZSBhbmFseXNlIHZhbGlkZSB6b3UgemlqbiBpcyBoZXQgbm9vZHpha2VsaWprIGRhdCBkZSBzdWJqZWN0ZW4gdm9sbGVkaWcgcmFuZG9tIHdvcmRlbiBnZXRyb2trZW4gdWl0IGRlIHBvcHVsYXRpZSBuYWFyIHdhYXIgd2Ugb256ZSBjb25jbHVzaWVzIHdlbnNlbiB0ZSB2ZXJhbGdlbWVuZW4uCgotIFZvbGxlZGlnIHJhbmRvbSB0cmVra2VuIHZhbiBkZSBwb3B1bGF0aWUgaW1wbGljZWVydCBkYXQ6CgogICAgLSBhbGxlIHN1YmplY3RlbiB2YW4gZGUgcG9wdWxhdGllIGV2ZW52ZWVsIGthbnMgaGViYmVuIG9tIGluIGRlIHN0ZWVrcHJvZWYgdGUgd29yZGVuIG9wZ2Vub21lbgogICAgLSBkZSBzZWxlY3RpZSB2YW4gZWVuIHN1YmplY3Qgb25hZmhhbmtlbGlqayBpcyB2YW4gZGUgYW5kZXJlIHN1YmplY3RlbiBpbiBkZSBzdGVla3Byb2VmLgoKCi0gRGUgc3RlZWtwcm9lZiBpcyBkYW4gcmVwcmVzZW50YXRpZWYgdm9vciBkZSBwb3B1bGF0aWUsIG1hYXIgaXMgbm9nIHN0ZWVkcyByYW5kb20uCgotIFdhdCBiZXRla2VudCBkaXQ/CgotLS0KCiMgVmFyaWFiaWxpdGVpdCB2YW4gc3RlZWtwcm9lZiB0b3Qgc3RlZWtwcm9lZgoKLSBPbSB0ZSBiZWdyaWpwZW4gZGF0IGVlbiBzdGVla3Byb2VmIHJhbmRvbSBpcyB6b3VkZW4gd2UgaGV0emVsZmRlIGV4cGVyaW1lbnQgdmVlbCBrZWVyIG1vZXRlbiBrdW5uZW4gaGVyaGFsZW4gKGByZXBlYXRlZCBzYW1wbGluZ2ApLgoKLSBEYW4gem91ZGVuIHdlIGluemljaHQga3VubmVuIGtyaWpnZW4gaG9lIGRlIGdlZ2V2ZW5zIHZlcmFuZGVyZW4gdmFuIHN0ZWVrcHJvZWYgdG90IHN0ZWVrcHJvZWYuCgotIE9tIGRpdCB0ZSBpbGx1c3RyZXJlbiB6dWxsZW4gd2UgZ2VicnVpayBtYWtlbiB2YW4gZWVuIGhlbGUgZ3JvdGUgc3R1ZGllLgoKLSBVaXQgZGllIHN0dWRpZSB6dWxsZW4gd2UgZGFuIGhlcmhhYWxkZWxpamsga2xlaW5lIHN0ZWVrcHJvZXZlbiB0cmVra2VuIG9tIHRlIGJlZ3JpanBlbiBob2UgZGUgZ2VnZXZlbnMgZW4gc3RhdGlzdGlla2VuIHZlcmFuZGVyZW4gdmFuIHN0ZWVrcHJvZWYgdG90IHN0ZWVrcHJvZWYuIE9mIG9tIG1ldCBhbmRlcmUgd29vcmRlbiBuYSB0ZSBnYWFuIHdhdCBkZSB2YXJpYWJpbGl0ZWl0IGlzIHR1c3NlbiBzdGVla3Byb2V2ZW4uCgotLS0KCk5hdGlvbmFsIEhlYWx0aCBOSGFuZXMgc3R1ZHkKCiAgLSBTaW5kcyAxOTYwIHdvcmRlbiBlbGsgamFhciBtZW5zZW4gdmFuIGFsbGUgbGVlZnRpamRlbiBnZcOvbnRlcnZpZXdkIGJpaiBoZW4gdGh1aXMuCiAgLSBFciBtYWFrdCBvb2sgZWVuIGdlem9uZGhlaWRzb25kZXJ6b2VrIGRlZWwgdWl0IHZhbiBkZSBzdHVkeSBkaWUgaW4gZWVuIG1vYmllbCBvbmRlcnpvZWtzY2VudHJ1bSB3b3JkdCBhZmdlbm9tZW4uCiAgLSBXZSB6dWxsZW4gZGV6ZSBncm90ZSBzdHVkaWUgZ2VicnVpa2VuIG9tIGF0IHJhbmRvbSBwZXJzb25lbiB0ZSBzZWxlY3RlcmVuIHZhbiBkZSBBbWVyaWthYW5zZSBwb3B1bGF0aWUuCiAgLSBEYXQgemFsIGluemljaHQgZ2V2ZW4gaW4gaG9lIGRlIGdlZ2V2ZW5zIGVuIHJlc3VsdGF0ZW4gdmFuIGVlbiBhbmFseXNlIHp1bGxlbiB2YXJpw6tyZW4gdmFuIHN0ZWVrcHJvZWYgdG90IHN0ZWVrcHJvZWYuCiAgLSBEZSBkYXRhIHZhbiBkZXplIHN0dWRpZSBpcyB0ZXJ1ZyB0ZSB2aW5kZW4gaW4gaGV0IFIgcGFra2V0IGBOSEFORVNgCgotLS0KCmBgYHtyfQpsaWJyYXJ5KE5IQU5FUykKaGVhZChOSEFORVMpCmdsaW1wc2UoTkhBTkVTKQpgYGAKCi0tLQoKIyMgRGF0YSBleHBsb3JhdGllCgoKCk9uZGVyem9la3N2cmFhZzogaG9lIHZlcnNjaGlsdCBkZSBsZW5ndGUgdmFuIHZvbHdhc3NlbiBtYW5uZW4gZW4gdnJvdXdlbi4KCjEuIFdlIHBpcGVuIGRlIGRhdGFzZXQgbmFhciBkZSBmdW5jdGlvbiBgZmlsdGVyYCBvbSBkZSBkYXRhIHRlIGZpbHRlcmVuIHZvbGdlbnMgbGVlZnRpamQuICAKMi4gV2UgcGxvdHRlbiBkZSBsZW5ndGUgbWV0aW5nZW4uCiAgICAtIFdlIHNlbGVjdGVyZW4gZGUgZGF0YSBkYXRhIG1ldCBoZXQgY29tbWFuZG8gYGdncGxvdChhZXMoeD1sZW5ndGUpKWAKICAgIC0gV2Ugdm9lZ2VuIGVlbiBoaXN0b2dyYW0gdG9lIG1ldCBoZXQgY29tbWFuZG8gYGdlb21faGlzdG9ncmFtKClgCiAgICAtIFdlIG1ha2VuIHR3ZWUgdmVydGlrYWxlIHBhbmVscyBtZXQgaGV0IGNvbW1hbmRvIGBmYWNldF9ncmlkKEdlbmRlcn4uKWAKICAgIC0gV2UgdmVyYW5kZXJlbiBoZXQgbGFiZWwgdmFuIGRlIHgtYXMgbWV0IGRlIGB4bGFiYCBmdW5jdGllLgoKYGBge3J9Ck5IQU5FUyU+JSAgCiAgZmlsdGVyKEFnZSA+IDE4ICYgIWlzLm5hKEhlaWdodCkpICU+JQogIGdncGxvdChhZXMoeCA9IEhlaWdodCkpKwogIGdlb21faGlzdG9ncmFtKCkgKwogIGZhY2V0X2dyaWQoR2VuZGVyIH4gLikgKwogIHhsYWIoIkxlbmd0ZSAoY20pIikKYGBgCgotLS0KCldlIHppZW4gZGF0IGRlIGRhdGEgbnUgbWluIG9mIG1lZXIgc3ltbWV0cmlzY2ggdmVyZGVlbGQgemlqbiBlbiBlZW4ga2xva3Zvcm0gaGViYmVuLiAgCkRhdCB6YWwgb25zIHRvZSBsYXRlbiBvbSBkZSBkYXRhIHZlcmRlciBzYW1lbiB0ZSB2YXR0ZW4gZG9vciBnZWJydWlrIHRlIG1ha2VuIHZhbiB0d2VlIHN0YXRpc3RpZWtlbjogaGV0IGdlbWlkZGVsZGUgZW4gZGUgc3RhbmRhYXJkIGRldmlhdGllIHdhdCBlZW4gbWFhdCBpcyB2b29yIGRlIHNwcmVpZGluZyB2YW4gZGUgZ2VnZXZlbnMgcm9uZCBoZXQgZ2VtaWRkZWxkZS4KCi0tLQoKV2UgbWFrZW4gbnUgZWVuIHN1YnNldCB2YW4gZGUgZGF0YSBkaWUgd2UgenVsbGVuIGdlYnJ1aWtlbiBvbSBhYW4gdGUgdG9uZW4gaG9lIGRlIHZhcmlhYmlsaXRlaXQgaW4ga2xlaW5lIHN0ZWVrcHJvZXZlbiBrYW4gdmFyacOrcmVuIHZhbiBzdGVla3Byb2VmIHRvdCBzdGVla3Byb2VmLgoKICAxLiBXZSBmaWx0ZXJlbiBvcCBsZWVmdGlqZCBlbiB2ZXJ3aWpkZXJlbiBvbnRicmVrZW5kZW4gZ2VnZXZlbnMgKE5BLCBOb3QgQXZhaWxhYmxlKS4KICAyLiBXZSBzZWxlY3RlcmVuIGVua2VsIGhldCBnZXNsYWNodCBlbiBMZW5ndGUgem9kYXQgZGUgZGF0YXNldCBnZWVuIG9ubm9kaWdlIHZhcmlhYmVsZW4gYmV2YXQuCgpgYGB7cn0KbmhhbmVzU3ViIDwtIE5IQU5FUyAlPiUKICBmaWx0ZXIoQWdlID4gMjUgJiAhaXMubmEoSGVpZ2h0KSkgJT4lCiAgc2VsZWN0KGMoIkdlbmRlciIsIkhlaWdodCIpKQpgYGAKCi0tLQoKV2UgYmVyZWtlbmVuIGhldCBnZW1pZGRlbGRlIGVuIGRlIHN0YW5kYWFyZCBkZXZpYXRpZSB2b29yIGRlIGxlbmd0ZSB2b29yIG1hbm5lbiBlbiB2cm91d2VuIGluIGRlIGdyb3RlIGRhdGFzZXQuCldlIGdyb2VwZXJlbiBkZSBkYXRhIGhpZXJ2b29yIG9wIGJhc2lzIHZhbiBoZXQgZ2VzbGFjaHQgKHZhcmlhYmxlIEdlbmRlcikuCgoKYGBge3J9CgpIZWlnaHRTdW0gPC0gbmhhbmVzU3ViICU+JQogIGdyb3VwX2J5KEdlbmRlcikgJT4lCiAgc3VtbWFyaXplX2F0KCJIZWlnaHQiLAogICAgICAgICAgICAgICBsaXN0KG1lYW4gPSBtZWFuLAogICAgICAgICAgICAgICBzZCA9IHNkKQogICAgICAgICAgICAgICkKCmtuaXRyOjprYWJsZSgKICBIZWlnaHRTdW0gJT4lCiAgbXV0YXRlX2lmKGlzLm51bWVyaWMsIHJvdW5kLCBkaWdpdHM9MSkKICApCmBgYAoKLS0tCgojIyBFeHBlcmltZW50CgotIFN0ZWwgZGF0IHdlIGdlZW4gdG9lZ2FuZyBoZWJiZW4gdG90IGRlIG1ldGluZ2VuIHZhbiBkZSBOSEFORVMgc3R1ZGllLgoKLSBXZSB6b3VkZW4gZGFuIGVlbiBleHBlcmltZW50IG9wIG1vZXRlbiB6ZXR0ZW4gb20gbWV0aW5nZW4gYmlqIG1hbm5lbiBlbiB2cm91d2VuIHRlIGRvZW4uCgotIFZlcm9uZGVyc3RlbCBkYXQgd2UgYnVkZ2V0IGhlYmJlbiBvbSBtZXRpbmdlbiBiaWogNSBtYW5uZW4gZW4gNSB2cm91d2VuIHRlIGRvZW4uCgotIFdlIHpvdWRlbiBkYW4gNSBtYW5uZW4gZW4gNSB2cm91d2VuIGJvdmVuIGRlIDI1IGphYXIgYXQgcmFuZG9tIHNlbGVjdGVyZW4gdWl0IGRlIEFtZXJpa2FhbnNlIHBvcHVsYXRpZS4KCi0gV2Uga3VubmVuIGRpdCBleHBlcmltZW50IHNpbXVsZXJlbiBkb29yIDUgdnJvdXdlbiBlbiA1IG1hbm5lbiBhdCByYW5kb20gdGUgc2VsZWN0ZXJlbiB1aXQgZGUgTkhBTkVTIHN0dWRpZS4KCi0tLQoKYGBge3J9CnNldC5zZWVkKDEwMDAwMDEpCm5TYW1wIDwtIDUKZmVtIDwtIG5oYW5lc1N1YiAlPiUKICBmaWx0ZXIoR2VuZGVyPT0iZmVtYWxlIikgJT4lCiAgc2FtcGxlX24oc2l6ZT01KQoKbWFsIDwtIG5oYW5lc1N1YiAlPiUKICBmaWx0ZXIoR2VuZGVyPT0ibWFsZSIpICU+JQogIHNhbXBsZV9uKHNpemU9NSkKCnNhbXAxIDwtIHJiaW5kKGZlbSxtYWwpCgpzYW1wMQpgYGAKCi0tLQoKRGF0YSBFeHBsb3JhdGllCgpgYGB7cn0Kc2FtcDEgJT4lCiAgZ2dwbG90KGFlcyh4PUhlaWdodCkpICsKICBnZW9tX2hpc3RvZ3JhbSgpICsKICBmYWNldF9ncmlkKEdlbmRlcn4uKSArCiAgeGxhYigiTGVuZ3RlIChjbSkiKQoKSGVpZ2h0U3VtRXhwMSA8LSBzYW1wMSAlPiUKICBncm91cF9ieShHZW5kZXIpICU+JQogIHN1bW1hcml6ZV9hdCgiSGVpZ2h0IiwKICAgICAgICAgICAgICAgbGlzdChtZWFuID0gbWVhbiwKICAgICAgICAgICAgICAgICAgICAgIHNkID0gc2QpCiAgICAgICAgICAgICAgICAgICkKSGVpZ2h0U3VtRXhwMQpgYGAKCkhpc3RvZ3JhbSBpcyBuaWV0IHppbnZvbCBhbHMgd2UgbWFhciB6byB3ZWluaWcgZGF0YXB1bnRlbiBoZWJiZW4uCgotLS0KCgpCb3hwbG90IGlzIGJldGVyOgoKYGBge3IgZWNobz1GQUxTRX0Kc2FtcDEgJT4lCiAgZ2dwbG90KGFlcyh4ID0gR2VuZGVyLHkgPSBIZWlnaHQpKSArCiAgZ2VvbV9ib3hwbG90KG91dGxpZXIuc2hhcGUgPSBOQSkgKwogIGdlb21fcG9pbnQocG9zaXRpb24gPSAiaml0dGVyIikgKwogIGdlb21fcG9pbnQoCiAgICBhZXMoeCA9IDEsIHkgPSBIZWlnaHRTdW1FeHAxJG1lYW5bMV0pLAogICAgc2l6ZSA9IDMsCiAgICBwY2ggPSAxNywKICAgIGNvbG9yPSJkYXJrcmVkIikgKwogIGdlb21fcG9pbnQoCiAgICBhZXMoeCA9IDIsIHkgPSBIZWlnaHRTdW1FeHAxJG1lYW5bMV0pLAogICAgc2l6ZSA9IDMsCiAgICBwY2ggPSAxNywKICAgIGNvbG9yID0gImRhcmtyZWQiKSArCiAgeWxhYigiSGVpZ2h0IChjbSkiKQpgYGAKCi0tLQoKV2Ugdm9lcmVuIGhpZXIgb29rIGVlbiB0LXRlc3QgdWl0LgoKYGBge3J9CnQudGVzdChIZWlnaHR+R2VuZGVyLGRhdGE9c2FtcDEpCmBgYAoKSW4gaGV0IGV4cGVyaW1lbnQgemlqbiB2cm91d2VuIHppam4gZ2VtaWRkZWxkIGByIHJvdW5kKGFicyhIZWlnaHRTdW1FeHAxJG1lYW5bMV0tSGVpZ2h0U3VtRXhwMSRtZWFuWzJdKSwyKWAgY20gYHIgaWZlbHNlKEhlaWdodFN1bUV4cDEkbWVhblsxXT5IZWlnaHRTdW1FeHAxJG1lYW5bMl0sImdyb3RlciIsImtsZWluZXIiKWAgZGFuIG1hbm5lbi4gRW4gYWxzIHdlIGVlbiBzdGF0aXN0aXNjaGUgdGVzdCB1aXR2b2VyZW4gKHppZSBob29mZHN0dWsgNTogU3RhdGlzdGlzY2hlIGJlc2x1aXR2b3JtaW5nKSBrdW5uZW4gd2UgYmVzbHVpdGVuIGRhdCBkaXQgdmVyc2NoaWwgc3RhdGlzdGlzY2ggYHIgaWZlbHNlKHQudGVzdChIZWlnaHR+R2VuZGVyLHNhbXAxKSRwLnZhbHVlIDwgMC4wNSwic2lnbmlmaWNhbnQiLCJuaWV0IHNpZ25pZmljYW50IilgIGlzLgoKLS0tCgojIyBIZXJoYWFsIGhldCBleHBlcmltZW50CgpBbHMgd2UgaGV0IGV4cGVyaW1lbnQgaGVyaGFsZW4gc2VsZWN0ZXJlbiB3ZSBhbmRlcmUgbWVuc2VuIGVuIHZlcmtyaWpnZW4gd2UgYW5kZXJlIHJlc3VsdGF0ZW4uCgoKYGBge3J9CmZlbSA8LSBuaGFuZXNTdWIgJT4lCiAgZmlsdGVyKEdlbmRlcj09ImZlbWFsZSIpICU+JQogIHNhbXBsZV9uKHNpemU9NSkKCm1hbCA8LSBuaGFuZXNTdWIgJT4lCiAgZmlsdGVyKEdlbmRlcj09Im1hbGUiKSAlPiUKICBzYW1wbGVfbihzaXplPTUpCgpzYW1wMiA8LSByYmluZChmZW0sbWFsKQoKSGVpZ2h0U3VtRXhwMiA8LSBzYW1wMiAlPiUKICBncm91cF9ieShHZW5kZXIpICU+JQogIHN1bW1hcml6ZV9hdCgiSGVpZ2h0IiwKICAgICAgICAgICAgICAgbGlzdChtZWFuPW1lYW4sCiAgICAgICAgICAgICAgICAgICAgc2Q9c2QpCiAgICAgICAgICAgICAgKQpIZWlnaHRTdW1FeHAyCgpzYW1wMiAlPiUKICBnZ3Bsb3QoYWVzKHggPSBHZW5kZXIseSA9IEhlaWdodCkpICsKICBnZW9tX2JveHBsb3Qob3V0bGllci5zaGFwZSA9IE5BKSArCiAgZ2VvbV9wb2ludChwb3NpdGlvbiA9ICJqaXR0ZXIiKSArCiAgZ2VvbV9wb2ludCgKICAgIGFlcyh4ID0gMSwgeSA9IEhlaWdodFN1bUV4cDEkbWVhblsxXSksCiAgICBzaXplID0gMywKICAgIHBjaCA9IDE3LAogICAgY29sb3I9ImRhcmtyZWQiKSArCiAgZ2VvbV9wb2ludCgKICAgIGFlcyh4ID0gMiwgeSA9IEhlaWdodFN1bUV4cDEkbWVhblsxXSksCiAgICBzaXplID0gMywKICAgIHBjaCA9IDE3LAogICAgY29sb3IgPSAiZGFya3JlZCIpICsKICB5bGFiKCJIZWlnaHQgKGNtKSIpCgp0LnRlc3QoSGVpZ2h0IH4gR2VuZGVyLCBkYXRhPXNhbXAyKQpgYGAKCgpJbiBkZSBuaWV1d2Ugc3RlZWtwcm9lZiB6aWpuIHZyb3V3ZW4gemlqbiBnZW1pZGRlbGQgYHIgcm91bmQoYWJzKEhlaWdodFN1bUV4cDIkbWVhblsxXS1IZWlnaHRTdW1FeHAyJG1lYW5bMl0pLDIpYCBjbSBgciBpZmVsc2UoSGVpZ2h0U3VtRXhwMiRtZWFuWzFdPkhlaWdodFN1bUV4cDIkbWVhblsyXSwiZ3JvdGVyIiwia2xlaW5lciIpYCBkYW4gbWFubmVuLiBFbiBkaXQgdmVyc2NoaWwgaXMgc3RhdGlzdGlzY2ggYHIgaWZlbHNlKHQudGVzdChIZWlnaHR+R2VuZGVyLHNhbXAyLHZhci5lcXVhbD1UUlVFKSRwLnZhbHVlIDwgMC4wNSwic2lnbmlmaWNhbnQiLCJuaWV0IHNpZ25pZmljYW50IilgCgoKLS0tCgojIyBIZXJoYWFsIGhldCBleHBlcmltZW50IG9wbmlldXcKCmBgYHtyfQpzZWVkIDwtIDEzMzY2MDIKZmVtIDwtIG5oYW5lc1N1YiAlPiUKICBmaWx0ZXIoR2VuZGVyPT0iZmVtYWxlIikgJT4lCiAgc2FtcGxlX24oc2l6ZT01KQoKbWFsIDwtIG5oYW5lc1N1YiAlPiUKICBmaWx0ZXIoR2VuZGVyPT0ibWFsZSIpICU+JQogIHNhbXBsZV9uKHNpemU9NSkKCnNhbXAzIDwtIHJiaW5kKGZlbSxtYWwpCgpIZWlnaHRTdW1FeHAzIDwtIHNhbXAzICU+JQogIGdyb3VwX2J5KEdlbmRlcikgJT4lCiAgc3VtbWFyaXplX2F0KCJIZWlnaHQiLAogICAgICAgICAgICAgICBsaXN0KG1lYW49bWVhbiwKICAgICAgICAgICAgICAgICAgICBzZD1zZCkKICAgICAgICAgICAgICApCkhlaWdodFN1bUV4cDMKCnNhbXAzICU+JQogIGdncGxvdChhZXMoeCA9IEdlbmRlcix5ID0gSGVpZ2h0KSkgKwogIGdlb21fYm94cGxvdChvdXRsaWVyLnNoYXBlID0gTkEpICsKICBnZW9tX3BvaW50KHBvc2l0aW9uID0gImppdHRlciIpICsKICBnZW9tX3BvaW50KAogICAgYWVzKHggPSAxLCB5ID0gSGVpZ2h0U3VtRXhwMSRtZWFuWzFdKSwKICAgIHNpemUgPSAzLAogICAgcGNoID0gMTcsCiAgICBjb2xvcj0iZGFya3JlZCIpICsKICBnZW9tX3BvaW50KAogICAgYWVzKHggPSAyLCB5ID0gSGVpZ2h0U3VtRXhwMSRtZWFuWzFdKSwKICAgIHNpemUgPSAzLAogICAgcGNoID0gMTcsCiAgICBjb2xvciA9ICJkYXJrcmVkIikgKwogIHlsYWIoIkhlaWdodCAoY20pIikKCnQudGVzdChIZWlnaHQgfiBHZW5kZXIsIGRhdGE9c2FtcDMpCmBgYAoKSW4gZGUgbmlldXdlIHN0ZWVrcHJvZWYgemlqbiB2cm91d2VuIGdlbWlkZGVsZCBgciByb3VuZChhYnMoSGVpZ2h0U3VtRXhwMyRtZWFuWzFdLUhlaWdodFN1bUV4cDMkbWVhblsyXSksMilgIGNtIGByIGlmZWxzZShIZWlnaHRTdW1FeHAzJG1lYW5bMV0+SGVpZ2h0U3VtRXhwMyRtZWFuWzJdLCJncm90ZXIiLCJrbGVpbmVyIilgIGRhbiBtYW5uZW4uIEVuIGRpdCB2ZXJzY2hpbCBpcyBzdGF0aXN0aXNjaCBgciBpZmVsc2UodC50ZXN0KEhlaWdodH5HZW5kZXIsc2FtcDMsdmFyLmVxdWFsPVRSVUUpJHAudmFsdWUgPCAwLjA1LCJzaWduaWZpY2FudCIsIm5pZXQgc2lnbmlmaWNhbnQiKWAKCi0tLQoKIyMgU2FtZW52YXR0aW5nCgotIFdlIHRyb2trZW4gYXQgcmFuZG9tIGFuZGVyZSBwcm9lZnBlcnNvbmVuIGluIGVsa2Ugc3RlZWtwcm9lZgoKLSBIaWVyZG9vciB2ZXJzY2hpbGxlbiBsZW5ndGVtZXRpbmdlbiB2YW4gc3RlZWtwcm9lZiB0b3Qgc3RlZWtwcm9lZi4KCi0gRHVzIG9vayBkZSBnZXNjaGF0dGUgZ2VtaWRkZWxkZXMgZW4gc3RhbmRhYXJkIGRldmlhdGllcy4KCi0gQmlqZ2V2b2xnIHppam4gb256ZSBjb25jbHVzaWVzIG9vayBvbnpla2VyIGVuIGt1bm5lbiBkZXplIHdpanppZ2VuIHZhbiBzdGVla3Byb2VmIHRvdCBzdGVla3Byb2VmLgoKLSBTdGVla3Byb2V2ZW4gd2FhcmJpaiBoZXQgZWZmZWN0IHRlZ2VuZ2VzdGVsZCBpcyBhYW4gZGF0IGluIGRlIHBvcHVsYXRpZSBlbiB3YWFyYmlqIHdlIGJlc2x1aXRlbiBkYXQgaGV0IHZlcnNjaGlsIHNpZ25pZmljYW50IGlzLCB6aWpuIHplbGR6YWFtLgoKJFxyaWdodGFycm93JCBNZXQgc3RhdGlzdGllayBjb250cm9sZXJlbiB3ZSBkZSBrYW5zIG9wIGhldCB0cmVra2VuIGZvdXRlIGNvbmNsdXNpZXMuCgotIERpdCB3b3JkdCBpbiBkZSBvbmRlcnN0YWFuZGUgY29kZSBnZcOvbGx1c3RyZWVyZC4gV2UgdHJla2tlbiAxMDAwMCBoZXJoYWFsZGUgc3RlZWtwcm9ldmVuIHZhbiA1IHZyb3V3ZW4gZW4gNSBtYW5uZW4gdWl0IGRlIE5IQU5FUyBzdHVkaWUuCgpgYGB7cn0KIyBBYW50YWwgc2ltdWxhdGllcyBlbiBzdGVla3Byb2VmZ3Jvb3R0ZSBwZXIgZ3JvZXAKblNpbSA8LSAxMDAwMApuU2FtcCA8LSA1CgojIFdlIGZpbHRlcmVuIGRlIGRhdGEgdm9vcmFmIHpvZGF0IHdlIGRpdCBuaWV0IHRlbGtlbnMgb3BuaWV1dyBob2V2ZW4gdGUgZG9lbgpmZW0gPC0gbmhhbmVzU3ViICU+JQogIGZpbHRlcihHZW5kZXIgPT0gImZlbWFsZSIpCgptYWwgPC0gbmhhbmVzU3ViICU+JQogIGZpbHRlcihHZW5kZXIgPT0gIm1hbGUiKQoKIyBTaW11bGF0aWUgc3R1ZGllCiMgT20gc25lbGxlIGZ1bmN0aWVzIHRlIGt1bm5lbiBnZWJydWlrZW4gbmVtZW4gd2UgZWVyc3QgblNpbSBzdGVla3Byb2V2ZW4gZW4gYmVyZWtlbmVuIHdlIGRhYXJuYSBhbGxlcy4KCmZlbVNhbXBzIDwtIG1hbFNhbXBzIDwtbWF0cml4KE5BLCBucm93PW5TYW1wLCBuY29sPW5TaW0pCmZvciAoaSBpbiAxOm5TaW0pCnsKICBmZW1TYW1wc1ssaV0gPC0gc2FtcGxlKGZlbSRIZWlnaHQsIG5TYW1wKQogIG1hbFNhbXBzWyxpXSA8LSBzYW1wbGUobWFsJEhlaWdodCwgblNhbXApCn0KCnJlcyA8LSBkYXRhLmZyYW1lKAogIHZlcnNjaGlsPWNvbE1lYW5zKGZlbVNhbXBzKSAtIGNvbE1lYW5zKG1hbFNhbXBzKSwKICBSZmFzdDo6dHRlc3RzKGZlbVNhbXBzLCBtYWxTYW1wcykKICApCgpzdW0ocmVzJHB2YWx1ZSA8IDAuMDUgJiByZXMkdmVyc2NoaWwgPCAwKQpzdW0ocmVzJHB2YWx1ZSA+PSAwLjA1KQpzdW0ocmVzJHB2YWx1ZSA8IDAuMDUgJiByZXMkdmVyc2NoaWw+MCkKCnJlcyAlPiUKICBnZ3Bsb3QoYWVzKHg9dmVyc2NoaWwseT0tbG9nMTAocHZhbHVlKSxjb2xvcj1wdmFsdWUgPCAwLjA1KSkgKwogIGdlb21fcG9pbnQoKSArCiAgeGxhYigiR2VtaWRkZWxkIFZlcnNjaGlsIChjbSkiKSArCiAgeWxhYigiU3RhdGlzdGlzY2hlIFNpZ25pZmljYW50aWUgKC1sb2cxMCBwKSIpCgpyZXMgJT4lCiAgZ2dwbG90KGFlcyh5ID0gdmVyc2NoaWwpKSArCiAgZ2VvbV9ib3hwbG90KCkgKwogIHlsYWIoIkdlbWlkZGVsZCBWZXJzY2hpbCAoY20pIikKICB4bGFiKCIiKQpgYGAKCk9wIGJhc2lzIHZhbiAxMCAwMDAgc3RlZWtwcm9ldmVuIHZhbiA1IG1hbm5lbiBlbiA1IHZyb3V3ZW4gemFnZW4gd2UgZGF0IGluIGByIHN1bShyZXMkcHZhbHVlPDAuMDUmcmVzJHZlcnNjaGlsPDApYCBzdGVla3Byb2V2ZW4gdnJvdXdlbiBnZW1pZGRlbGQgc2lnbmlmaWNhbnQga2xlaW5lciB6aWpuIGRhbiBtYW5uZW4uIEluIGByIHN1bShyZXMkcHZhbHVlPj0wLjA1KWAgc3RlZWtwcm9ldmVuIGJlc2x1aXRlbiB3ZSBkYXQgdnJvdXdlbiBlbiBtYW5uZW4gZ2VtaWRkZWxkIG5pZXQgc2lnbmlmaWNhbnQgdmVyc2NoaWxsZW4gaW4gbGVuZ3RlLiBFbiBpbiBgciBzdW0ocmVzJHB2YWx1ZTwwLjA1JnJlcyR2ZXJzY2hpbD4wKWAgYmVzbHVpdGVuIHdlIGRhdCB2cm91d2VuIGdlbWlkZGVsZCBzaWduaWZpY2FudCBncm90ZXIgemlqbiBkYW4gbWFubmVuLgoKLSBEZSBzdGVla3Byb2VmIGRpZSB3ZSB0b29uZGVuIHdhYXJ1aXQgd2Ugem91ZGVuIGJlc2x1aXRlbiBkYXQgdnJvdXdlbiBzaWduaWZpY2FudCBncm90ZXIgemlqbiBkYW4gbWFubmVuIGlzIGhlZWwgb253YWFyc2NoaWpubGlqay4gRXIgbW9lc3RlbiBgciBwYXN0ZShzZWVkKWAgc3RlZWtwcm9ldmVuIHdvcmRlbiBnZXRyb2trZW4gb20gZGV6ZSBleHRyZW1lIHN0ZWVrcHJvZWYgdGUgdmluZGVuLgoKSGV0IGZlaXQgZGF0IHdlIGluIHZlZWwgc3RlZWtwcm9ldmVuIHJlc3VsdGF0ZW4gdmluZGVuIGRpZSBzdGF0aXN0aXNjaCBuaWV0IHNpZ25pZmljYW50IHppam4ga29tdCBvbWRhdCBkZSBzdGF0aXN0aXNjaGUgdG9ldHMgZWVuIHRlIGxhZ2Uga3JhY2h0IGhlZWZ0IG9tIGhldCB2ZXJzY2hpbCB0ZSBkZXRlY3RlcmVuIHdhbm5lZXIgZXIgbWFhciA1IG9ic2VydmF0aWVzIHppam4gcGVyIGdyb2VwLgoKLS0tCgojIyBHcm90ZXJlIHN0ZWVrcHJvZWY/CgpXYXQgZ2ViZXVydCBlciBhbHMgd2UgZGUgc3RlZWtwcm9lZiB2ZXJob2dlbiBuYWFyIDUwIG9ic2VydmF0aWVzIHBlciBncm9lcD8KCgpgYGB7cn0KIyBBYW50YWwgc2ltdWxhdGllcyBlbiBzdGVla3Byb2VmZ3Jvb3R0ZSBwZXIgZ3JvZXAKblNpbSA8LSAxMDAwMApuU2FtcCA8LSA1MAoKIyBXZSBmaWx0ZXJlbiBkZSBkYXRhIHZvb3JhZiB6b2RhdCB3ZSBkaXQgbmlldCB0ZWxrZW5zIG9wbmlldXcgaG9ldmVuIHRlIGRvZW4KZmVtIDwtIG5oYW5lc1N1YiAlPiUKICBmaWx0ZXIoR2VuZGVyID09ICJmZW1hbGUiKQoKbWFsIDwtIG5oYW5lc1N1YiAlPiUKICBmaWx0ZXIoR2VuZGVyID09ICJtYWxlIikKCiMgU2ltdWxhdGllIHN0dWRpZQojIE9tIHNuZWxsZSBmdW5jdGllcyB0ZSBrdW5uZW4gZ2VicnVpa2VuIG5lbWVuIHdlIGVlcnN0IG5TaW0gc3RlZWtwcm9ldmVuIGVuIGJlcmVrZW5lbiB3ZSBkYWFybmEgYWxsZXMuCgpmZW1TYW1wcyA8LSBtYWxTYW1wcyA8LSBtYXRyaXgoTkEsIG5yb3cgPSBuU2FtcCwgbmNvbCA9IG5TaW0pCmZvciAoaSBpbiAxOm5TaW0pCnsKICBmZW1TYW1wc1ssaV0gPC0gc2FtcGxlKGZlbSRIZWlnaHQsIG5TYW1wKQogIG1hbFNhbXBzWyxpXSA8LSBzYW1wbGUobWFsJEhlaWdodCwgblNhbXApCn0KCnJlcyA8LSBkYXRhLmZyYW1lKAogIHZlcnNjaGlsID0gY29sTWVhbnMoZmVtU2FtcHMpIC0gY29sTWVhbnMobWFsU2FtcHMpLAogIFJmYXN0Ojp0dGVzdHMoZmVtU2FtcHMsIG1hbFNhbXBzKQogICkKCnN1bShyZXMkcHZhbHVlIDwgMC4wNSAmIHJlcyR2ZXJzY2hpbCA8IDApCnN1bShyZXMkcHZhbHVlID49IDAuMDUpCnN1bShyZXMkcHZhbHVlIDwgMC4wNSAmIHJlcyR2ZXJzY2hpbCA+IDApCgpyZXMgJT4lCiAgZ2dwbG90KGFlcyh4PXZlcnNjaGlsLHk9LWxvZzEwKHB2YWx1ZSksY29sb3I9cHZhbHVlPDAuMDUpKSArCiAgZ2VvbV9wb2ludCgpICsKICB4bGFiKCJHZW1pZGRlbGQgVmVyc2NoaWwgKGNtKSIpICsKICB5bGFiKCJTdGF0aXN0aXNjaGUgU2lnbmlmaWNhbnRpZSAoLWxvZzEwIHApIikKCnJlcyAlPiUKICBnZ3Bsb3QoYWVzKHk9dmVyc2NoaWwpKSArCiAgZ2VvbV9ib3hwbG90KCkgKwogIHlsYWIoIkdlbWlkZGVsZCBWZXJzY2hpbCAoY20pIikKICB4bGFiKCIiKQpgYGAKCi0tLQoKIyBTYWxrIFN0dWR5CgotIEluIDE5MTYsIGJyYWsgZGUgZWVyc3RlIGdyb3RlIHBvbGlvIGVwaWRlbWllIHVpdCBpbiBkZSBVU0EuCi0gQmVnaW4gZGUgamFyZW4gNTAgb250d2lra2VsZGUgSm9obiBTYWxrIGVlbiB2YWNjaW4gbWV0IGJlbG92ZW5kZSByZXN1bHRhdGVuIGluIGhldCBsYWIuCi0gSW4gMTk1NCwgaGVlZnQgZGUgTmF0aW9uYWwgRm91bmRhdGlvbgpmb3IgSW5mYW50aWxlIFBhcmFseXNpcyAoTkZJUCkgZWVuIGdyb3RlIHN0dWRpZSBvcGdlemV0IG9tIGRlIGVmZmVjdGl2aXRlaXQgdmFuIGhldCBTYWxrIHZhY2NpbiBuYSB0ZSBnYWFuLgotIFZlcm9uZGVyc3RlbCBkYXQgZGUgTkZJUCBpbiAxOTU0IGVlbiBncm9vdCBhYW50YWwga2luZGVyZW4gem91IGhlYmJlbiBnZXZhY2NpbmVlcmQsIHdhdCB6b3VkZW4gemUgZGFuIGt1bm5lbiBiZXNsdWl0ZW4gYWxzIGRlIHBvbGlvIGluY2lkZW50aWUgaW4gMTk1NCBsYWdlciB3YXMgZGFuIGluIDE5NTM/CgotLS0KCiMjIE5GSVAgU3R1ZHkKIyMjIERlc2lnbgoKLSBHcm90ZSBzaW11bHRhbmUgc3R1ZGllIG1ldCBnZXZhY2NpbmVlcmRlIGtpbmRlcmVuIChjYXNlcykgZW4gb25nZXZhY2NpbmVlcmRlIGtpbmRlcmVuIChjb250cm9sZXMpLgotIEluIHNjaG9sZW4gdmFuIGRpc3RyaWN0ZW4gbWV0IGhvZ2UgcG9saW8gaW5jaWRlbnRpZS4KLSBDYXNlczoga2luZGVyZW4gdmFuIGRlIHR3ZWVkZSBncmFhZCB2YW4gaGV0IGxhZ2VyIG9uZGVyd2lqcyB3YWFydmFuIGRlIG91ZGVycyB0b2VzdGVtZGVuIG1ldCB2YWNjaW5hdGllLgotIENvbnRyb2xlczoga2luZGVyZW4gdmFuIGRlIGVlcnN0ZSBlbiBkZXJkZSBncmFhZC4KCiMjIyBEYXRhCmBgYHtyfQpuZmlwIDwtIHRpYmJsZSgKICBncm91cD1jKCJjYXNlcyIsImNvbnRyb2xzIiwibm9Db25jZW50IiksCiAgZ3JhZGU9YygiZzIiLCJnMWczIiwiZzIiKSwKICB2YWNjaW49YygieWVzIiwibm8iLCJubyIpLAogIHRvdGFsPWMoMjIxOTk4LDcyNTE3MywxMjM2MDUpLAogIHBvbGlvPWMoNTQsMzkxLDU2KQogICkgJT4lCiAgbXV0YXRlKG5vUG9saW8gPSB0b3RhbCAtIHBvbGlvKQprbml0cjo6a2FibGUobmZpcCkKYGBgCgpWZXJnZWxpamsgZGUgcG9saW8gaW5jaWRlbnRpZT8KCi0tLQoKYGBge3J9Cm5maXAgPC0gbmZpcCAlPiUKICBtdXRhdGUoaW5jaWRlbmNlUE0gPSByb3VuZChuZmlwJHBvbGlvL25maXAkdG90YWwqMWU2LDApKQprbml0cjo6a2FibGUobmZpcCkKYGBgCgpXYXQga3VubmVuIHdlIGNvbmNsdWRlcmVuPwoKLS0tCgojIyBDb25mb3VuZGluZwoKCmBgYHtyLGVjaG89RkFMU0UsIGZpZy5hbGlnbiA9ICJjZW50ZXIiLG91dC53aWR0aCA9ICc1MCUnfQpwbG90KGMoMCwwLDEpLGMoLTIsMiwwKSxwY2g9YygiUyIsIlYiLCJQIikseGF4dD0ibm9uZSIseWF4dD0ibm9uZSIsYXhlcz1GQUxTRSx4bGFiPSIiLHlsYWI9IiIsY2V4PTQseWxpbT1jKC0yLjIsMi4yKSkKYXJyb3dzKHgwPTAuMSx4MT0uOSx5MD0xLjgseTE9MC4xLGx3ZD00KQphcnJvd3MoeDA9MC4xLHgxPS45LHkwPS0xLjgseTE9LTAuMixsd2Q9NCkKYXJyb3dzKHgwPTAseDE9MCx5MD0tMS40LHkxPTEuNCxsd2Q9NCkKYGBgCgoKLSBXZSBvYnNlcnZlcmVuIGVlbiBsYWdlcmUgcG9saW8gKFApIGluY2lkZW50aWUgdm9vciBraW5kZXJlbiBiaWogd2llIGRlIG91ZGVycyBnZWVuIHRvZXN0ZW1taW5nIGdhdmVuIGRhbiBpbiBkZSBjb250cm9sZSBncm9lcC4gIAoKLSBUb2VzdGVtbWluZyB2b29yIHZhY2NpbmF0aWUgKFYpIGlzIGdlYXNzb2NpZWVyZCBtZXQgZGUgc29jaW8tZWNvbm9taXNjaGUgc3RhdHVzIChTKS4KCi0gS2luZGVyZW4gdmFuIGxhZ2VyZSBzb2Npby1lY29ub21pc2NoZSBzdGF0dXMgemlqbiBtZWVyIHJlc2lzdGVudCB0ZWdlbiBkZSB6aWVrdGUuCgotIERlIGdyb2VwZW4gdmFuIGNhc2VzIGVuIGNvbnRyb2xlcyB6aWpuIG5pZXQgdmVyZ2VsaWprYmFhcgogICAgLSB2ZXJzY2hpbCBpbiBsZWVmdGlqZAogICAgLSB2ZXJzY2hpbCBpbiBzb2Npby1lY29ub21pc2NoZSBzdGF0dXMgZW4KICAgIC0gdmVyc2NoaWwgaW4gdmF0YmFhcmhlaWQgdm9vciBkZSB6aWVrdGUuCgotLS0KCiMjIFNhbGsgU3R1ZHkKCiMjIyBEZXNpZ24KRWVuIG5pZXV3ZSBzdHVkaWUgd2VyZCB1aXRnZXZvZXJkOiBkdWJiZWwgYmxpbmRlIGdlcmFuZG9taXNlZXJkZSBzdHVkaWUuCgogIC0gS2luZGVyZW4gd29yZGVuIGF0IHJhbmRvbSB0b2VnZXdlemVuIGFhbiBjb250cm9sZSBvZiBjYXNlIGFybSB2YW4gaGV0IGV4cGVyaW1lbnQgbmFkYXQgZGUgb3VkZXJzIHRvZXN0ZW1kZW4gbWV0IHZhY2NpbmF0aWUuCiAgLSBDb250cm9sZTogdmFjY2luYXRpZSBtZXQgcGxhY2VibwogIC0gVHJlYXRtZW50OiB2YWNjaW5hdGllIG1ldCB2YWNjaW4KICAtIERvdWJsZSBibGluZGluZzoKICAgIC0gb3VkZXJzIGVuIGtpbmRlcmVuIHdldGVuIG5pZXQgb2YgemUgd2VyZGVuIGdldmFjY2luZWVyZCBvZiBuaWV0CiAgICAtIG1lZGlzY2hlIHN0YWYgZW4gb25kZXJ6b2VrZXJzIHdldGVuIG5pZXQgb2YgaGV0IGtpbmQgaGV0IHZhY2NpbiBvZiBkZSBwbGFjZWJvIGtyZWVnCgotLS0KCiMjIyBEYXRhCgpgYGB7cn0Kc2FsayA8LSBkYXRhLmZyYW1lKAogIGdyb3VwPWMoImNhc2VzIiwiY29udHJvbCIsIm5vQ29uY2VudCIpLAogIHRyZWF0bWVudD1jKCJ2YWNjaW5lIiwicGxhY2VibyIsIm5vbmUiKSwKICB0b3RhbD1jKDIwMDc0NSwyMDEyMjksIDMzODc3OCkscG9saW89Yyg1NywxNDIsMTU3KQogICkgJT4lCiAgbXV0YXRlKAogICAgbm9Qb2xpbyA9IHRvdGFsLXBvbGlvLAogICAgaW5jaWRlbmNlUE0gPSByb3VuZChwb2xpby90b3RhbCoxZTYsMCkKICAgICkKa25pdHI6OmthYmxlKHNhbGspCmBgYAoKLSBXZSBvYnNlcnZlcmVuIGVlbiB2ZWVsIGdyb3RlciBlZmZlY3QgbnUgZGF0IGNhc2VzIGVuIGNvbnRyb2xlcyB2ZXJnZWxpamtiYWFyIHppam4sIGluY2lkZW50aWUgdmFuIHJlc3BlY3RpZXZlbGlqayBgciBzYWxrJGluY2lkZW5jZVBNWzFdYCAgYW5kIGByIHNhbGskaW5jaWRlbmNlUE1bMl1gIHBlciBtaWxqb2VuLgoKLSBEZSBwb2xpbyBpbmNpZGVudGllIHZvb3Iga2luZGVyZW4gZGllIGdlZW4gdG9lc3RlbW1pbmcgZ2V2ZW4gYmxpamZ0IHZlcmdlbGlqa2JhYXIgIGByIG5maXAkaW5jaWRlbmNlUE1bM11gIGFuZCBgciBzYWxrJGluY2lkZW5jZVBNWzNdYCBwZXIgbWlsam9lbiByZXNwZWN0aWV2ZWxpamsgaW4gdGhlIE5GSVAgYW5kIFNhbGsgc3R1ZHkuCgotLS0KCiMgUm9sIHZhbiBTdGF0aXN0aWVrCgotIFdlIGhlYmJlbiBnZXppZW4gZGF0CiAgICAtIGhldCBiZWxhbmdyaWprIGlzIG9tIGRlIHNjb3BlIHZhbiBkZSBzdHVkaWUgZ29lZCB0ZSBzcGVjaWZpw6tyZW4gdm9vciBkZSBzdGFydCB2YW4gaGV0IGV4cGVyaW1lbnQKICAgIC0gcmFuZG9taXNhdGllIG5vZGlnIGlzIG9tIGVlbiByZXByZXNlbnRhdGlldmUgc3RlZWtwcm9lZiB0ZSBuZW1lbgogICAgLSBzdGVla3Byb2VmIGdyb290dGUgaXMgaGVlbCBiZWxhbmdyaWprCiAgICAtIHdlIG1vZXRlbiBvbnMgYmV3dXN0IHppam4gdmFuIENvbmZvdW5kaW5nCiAgICAtIGVlbiBnb2VkZSBjb250cm9sZSBpcyBiZWxhbmdyaWprCgoKJFxyaWdodGFycm93JCBHb2VkZSBwcm9lZm9wemV0IGlzIGNydWNpYWFsIQoKLS0tCgotIFdlIGhlYmJlbiBvb2sgZ2VvYnNlcnZlZXJkIGRhdCBlciB2YXJpYWJpbGl0ZWl0IGlzIGluIGRlIHBvcHVsYXRpZQotIFdlIGt1bm5lbiBtYWFyIGVlbiBiZXBlcmt0ZSBzdGVla3Byb2VmIG5lbWVuIHVpdCBkZSBwb3B1bGF0aWUKCiRccmlnaHRhcnJvdyQgb256ZWtlcmhlaWQgaW4gZGUgcmVzdWx0YXRlbgokXHJpZ2h0YXJyb3ckIG9uemVrZXJoZWlkIGluIGRlIGNvbmNsdXNpZXMKCgotLS0KCi0gU3RhdGlzdGllayBpcyBkZSB3ZXRlbnNjaGFwIHZvb3IgaGV0CiAgICAxLiB2ZXJ6YW1lbGVuIChleHBlcmltZW50ZWVsIGRlc2lnbiksCiAgICAyLiBleHBsb3JlbiAoZGF0YSBleHBsb3JhdGlvbikgZW4KICAgIDMuIGxlcmVuIHZhbiBkYXRhIHpvZGF0IHdlIGhldGdlZW4gd2Ugb2JzZXJ2ZXJlbiBpbiBkZSBzdGVla3Byb2VmIHpvdWRlbiBrdW5uZW4gdmVyYWxnZW1lbmVuIG5hYXIgZGUgcG9wdWxhdGllIHRlcndpamwgd2UgZGUgb256ZWtlcmhlaWQgcXVhbnRpZmljZXJlbiwgY29udHJvbGVyZW4gZW4gcmFwcG9ydGVyZW4gKHN0YXRpc3Rpc2NoIG1vZGVsbGVyZW4gZW4gc3RhdGlzdGlzY2hlIGJlc2x1aXR2b3JtaW5nKS4KCi0gU3RhdGlzdGllayBzcGVlbHQgZGFhcm9tIGVlbiBoZWVsIGJlbGFuZ3JpamtlIHJvbCBpbiB6b3dhdCBhbGxlIHdldGVuc2NoYXBwZW4KCgojIFtIb21lXShodHRwczovL2d0cGIuZ2l0aHViLmlvL3NiYzIwLykgey19Cg==